summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java84
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourceUploadServlet.java373
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourcesServlet.java1146
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadEndpoint.java279
-rw-r--r--catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java25
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/ZipUtil.java143
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogicTest.java13
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarInfoTest.java14
-rw-r--r--catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/YamlTemplateParsingHandlerTest.java30
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CsarOperation.java29
-rw-r--r--catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OnboardingClient.java41
-rw-r--r--common-app-api/pom.xml14
-rw-r--r--common-app-api/src/main/java/org/openecomp/sdc/common/util/ZipUtil.java135
-rw-r--r--common-app-api/src/main/java/org/openecomp/sdc/common/zip/ZipUtils.java354
-rw-r--r--common-app-api/src/main/java/org/openecomp/sdc/common/zip/exception/ZipException.java31
-rw-r--r--common-app-api/src/main/java/org/openecomp/sdc/common/zip/exception/ZipSlipException.java27
-rw-r--r--common-app-api/src/test/java/org/openecomp/sdc/common/util/ZipUtilTest.java67
-rw-r--r--common-app-api/src/test/java/org/openecomp/sdc/common/zip/ZipUtilsTest.java172
-rw-r--r--common-app-api/src/test/resources/zip-slip/zip-slip-linux.zipbin0 -> 545 bytes
-rw-r--r--common-app-api/src/test/resources/zip-slip/zip-slip-windows.zipbin0 -> 547 bytes
-rw-r--r--common-app-api/src/test/resources/zip/extract-test.zipbin0 -> 2588 bytes
-rw-r--r--common-be/pom.xml2
-rw-r--r--common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/services/CommonUtil.java4
-rw-r--r--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.java4
-rw-r--r--openecomp-be/backend/openecomp-sdc-validation-manager/src/main/java/org/openecomp/sdc/validation/impl/UploadValidationManagerImpl.java78
-rw-r--r--openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/OrchestrationTemplateCSARHandler.java3
-rw-r--r--openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/upload/csar/UploadCSARFileTest.java4
-rw-r--r--openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/utils/CommonUtil.java118
-rw-r--r--openecomp-be/lib/openecomp-common-lib/src/test/java/org/openecomp/sdc/common/utils/CommonUtilTest.java18
-rw-r--r--openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/pom.xml18
-rw-r--r--openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/main/java/org/openecomp/core/utilities/file/FileUtils.java84
-rw-r--r--openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/test/java/org/openecomp/core/utilities/file/FileUtilsTest.java48
-rw-r--r--openecomp-be/lib/openecomp-sdc-enrichment-lib/openecomp-sdc-enrichment-impl/src/main/java/org/openecomp/sdc/enrichment/impl/external/artifact/MonitoringMibEnricher.java25
-rw-r--r--openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImpl.java61
-rw-r--r--openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImplTest.java37
-rw-r--r--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.java7
-rw-r--r--openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImpl.java5
-rw-r--r--openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/exportinfo/ExportDataCommand.java20
-rw-r--r--openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/importinfo/ImportDataCommand.java5
-rw-r--r--openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/util/ZipUtils.java104
-rw-r--r--test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/ToscaParserUtils.java289
-rw-r--r--test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/general/FileHandling.java148
-rw-r--r--test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/DeploymentValiditaion.java30
-rw-r--r--ui-ci/src/main/java/org/openecomp/sdc/ci/tests/utilities/FileHandling.java2
44 files changed, 1918 insertions, 2173 deletions
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java
index e00889646a..514576fcd8 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/AbstractValidationsServlet.java
@@ -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);
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourceUploadServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourceUploadServlet.java
index 3d7471ebc3..bfd7ce720a 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourceUploadServlet.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourceUploadServlet.java
@@ -1,187 +1,186 @@
-/*-
- * ============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));
- }
- }
-
- /********************************************************************************************************************/
-}
+/*-
+ * ============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));
+ }
+ }
+
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourcesServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourcesServlet.java
index 415fdcf562..03bed4762f 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourcesServlet.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/ResourcesServlet.java
@@ -1,574 +1,572 @@
-/*-
- * ============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.GroupBusinessLogic;
-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.Product;
-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;
- }
- }
-}
+/*-
+ * ============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;
+ }
+ }
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadEndpoint.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadEndpoint.java
index 5847a06e2b..5a148ef39e 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadEndpoint.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TypesUploadEndpoint.java
@@ -1,136 +1,143 @@
-/*-
- * ============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.io.IOException;
-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.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 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) throws IOException {
- accessValidations.validateUserExists(userId, "Annotation Types Creation");
- Wrapper<String> yamlStringWrapper = new Wrapper<>();
- AbstractValidationsServlet.extractZipContents(yamlStringWrapper, file);
- 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;
- }
-
-
-}
+/*-
+ * ============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;
+ }
+
+
+}
diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java
index 2f1357ea13..836565c1fe 100644
--- a/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java
+++ b/catalog-be/src/main/java/org/openecomp/sdc/be/tosca/CsarUtils.java
@@ -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
index 87e351be8a..0000000000
--- a/catalog-be/src/test/java/org/openecomp/sdc/ZipUtil.java
+++ /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);
- }
-}
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogicTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogicTest.java
index 2f7f5aab17..9bad9f4fa8 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogicTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarBusinessLogicTest.java
@@ -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);
}
}
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarInfoTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarInfoTest.java
index 3ae65c818a..69f9f5704d 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarInfoTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/csar/CsarInfoTest.java
@@ -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,
diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/YamlTemplateParsingHandlerTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/YamlTemplateParsingHandlerTest.java
index 19d1a17e84..8ae02c4f1b 100644
--- a/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/YamlTemplateParsingHandlerTest.java
+++ b/catalog-be/src/test/java/org/openecomp/sdc/be/components/impl/utils/YamlTemplateParsingHandlerTest.java
@@ -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);
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CsarOperation.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CsarOperation.java
index 9ae2f252c9..af8a68f410 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CsarOperation.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/CsarOperation.java
@@ -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
*
diff --git a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OnboardingClient.java b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OnboardingClient.java
index 8e1ee19358..ed0b43e38e 100644
--- a/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OnboardingClient.java
+++ b/catalog-model/src/main/java/org/openecomp/sdc/be/model/operations/impl/OnboardingClient.java
@@ -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);
}
}
diff --git a/common-app-api/pom.xml b/common-app-api/pom.xml
index 38d3bbec87..62bfb24b28 100644
--- a/common-app-api/pom.xml
+++ b/common-app-api/pom.xml
@@ -159,6 +159,20 @@
</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>
<version>${junit.version}</version>
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
index ec3c31cffe..0000000000
--- a/common-app-api/src/main/java/org/openecomp/sdc/common/util/ZipUtil.java
+++ /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
index 0000000000..d90377fc88
--- /dev/null
+++ b/common-app-api/src/main/java/org/openecomp/sdc/common/zip/ZipUtils.java
@@ -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
index 0000000000..414b4823ad
--- /dev/null
+++ b/common-app-api/src/main/java/org/openecomp/sdc/common/zip/exception/ZipException.java
@@ -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
index 0000000000..203e357f8f
--- /dev/null
+++ b/common-app-api/src/main/java/org/openecomp/sdc/common/zip/exception/ZipSlipException.java
@@ -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
index 71e8d1509a..0000000000
--- a/common-app-api/src/test/java/org/openecomp/sdc/common/util/ZipUtilTest.java
+++ /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
index 0000000000..d5fb3dcc8b
--- /dev/null
+++ b/common-app-api/src/test/java/org/openecomp/sdc/common/zip/ZipUtilsTest.java
@@ -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
index 0000000000..38b3f499de
--- /dev/null
+++ b/common-app-api/src/test/resources/zip-slip/zip-slip-linux.zip
Binary files 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
index 0000000000..3474c88bec
--- /dev/null
+++ b/common-app-api/src/test/resources/zip-slip/zip-slip-windows.zip
Binary files 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
index 0000000000..880452fdc7
--- /dev/null
+++ b/common-app-api/src/test/resources/zip/extract-test.zip
Binary files differ
diff --git a/common-be/pom.xml b/common-be/pom.xml
index f4b9ebf176..025e3a9ec0 100644
--- a/common-be/pom.xml
+++ b/common-be/pom.xml
@@ -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>
diff --git a/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/services/CommonUtil.java b/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/services/CommonUtil.java
index bb26e6a2b9..eb60d95889 100644
--- a/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/services/CommonUtil.java
+++ b/common/onap-tosca-datatype/src/main/java/org/onap/sdc/tosca/services/CommonUtil.java
@@ -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);
diff --git a/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 b/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
index 97bc375eb8..4f4258ad53 100644
--- a/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
+++ b/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
@@ -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);
}
}
diff --git a/openecomp-be/backend/openecomp-sdc-validation-manager/src/main/java/org/openecomp/sdc/validation/impl/UploadValidationManagerImpl.java b/openecomp-be/backend/openecomp-sdc-validation-manager/src/main/java/org/openecomp/sdc/validation/impl/UploadValidationManagerImpl.java
index 42c77b96d8..90f8ad369b 100644
--- a/openecomp-be/backend/openecomp-sdc-validation-manager/src/main/java/org/openecomp/sdc/validation/impl/UploadValidationManagerImpl.java
+++ b/openecomp-be/backend/openecomp-sdc-validation-manager/src/main/java/org/openecomp/sdc/validation/impl/UploadValidationManagerImpl.java
@@ -20,7 +20,11 @@
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 {
diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/OrchestrationTemplateCSARHandler.java b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/OrchestrationTemplateCSARHandler.java
index 61d1799aa0..8f0029aa83 100644
--- a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/OrchestrationTemplateCSARHandler.java
+++ b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/OrchestrationTemplateCSARHandler.java
@@ -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,
diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/upload/csar/UploadCSARFileTest.java b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/upload/csar/UploadCSARFileTest.java
index 122809896e..7a183c0dbb 100644
--- a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/upload/csar/UploadCSARFileTest.java
+++ b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/upload/csar/UploadCSARFileTest.java
@@ -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;
}
diff --git a/openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/utils/CommonUtil.java b/openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/utils/CommonUtil.java
index ae7d44efd8..8610ecb74b 100644
--- a/openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/utils/CommonUtil.java
+++ b/openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/utils/CommonUtil.java
@@ -20,62 +20,50 @@
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()) {
diff --git a/openecomp-be/lib/openecomp-common-lib/src/test/java/org/openecomp/sdc/common/utils/CommonUtilTest.java b/openecomp-be/lib/openecomp-common-lib/src/test/java/org/openecomp/sdc/common/utils/CommonUtilTest.java
index bc0bd137a0..119616a9be 100644
--- a/openecomp-be/lib/openecomp-common-lib/src/test/java/org/openecomp/sdc/common/utils/CommonUtilTest.java
+++ b/openecomp-be/lib/openecomp-common-lib/src/test/java/org/openecomp/sdc/common/utils/CommonUtilTest.java
@@ -16,23 +16,21 @@
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));
}
+
}
diff --git a/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/pom.xml b/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/pom.xml
index ce88037706..b86964f61f 100644
--- a/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/pom.xml
+++ b/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/pom.xml
@@ -66,6 +66,18 @@
<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>
<scope>test</scope>
@@ -85,6 +97,12 @@
<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>
diff --git a/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/main/java/org/openecomp/core/utilities/file/FileUtils.java b/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/main/java/org/openecomp/core/utilities/file/FileUtils.java
index c807d1b979..31338dcda4 100644
--- a/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/main/java/org/openecomp/core/utilities/file/FileUtils.java
+++ b/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/main/java/org/openecomp/core/utilities/file/FileUtils.java
@@ -16,11 +16,6 @@
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.");
- }
- }
-
}
diff --git a/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/test/java/org/openecomp/core/utilities/file/FileUtilsTest.java b/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/test/java/org/openecomp/core/utilities/file/FileUtilsTest.java
index a4928ac739..facfe57622 100644
--- a/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/test/java/org/openecomp/core/utilities/file/FileUtilsTest.java
+++ b/openecomp-be/lib/openecomp-core-lib/openecomp-utilities-lib/src/test/java/org/openecomp/core/utilities/file/FileUtilsTest.java
@@ -17,8 +17,12 @@
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());
}
}
diff --git a/openecomp-be/lib/openecomp-sdc-enrichment-lib/openecomp-sdc-enrichment-impl/src/main/java/org/openecomp/sdc/enrichment/impl/external/artifact/MonitoringMibEnricher.java b/openecomp-be/lib/openecomp-sdc-enrichment-lib/openecomp-sdc-enrichment-impl/src/main/java/org/openecomp/sdc/enrichment/impl/external/artifact/MonitoringMibEnricher.java
index dac9eae9ad..ca1fbe11b7 100644
--- a/openecomp-be/lib/openecomp-sdc-enrichment-lib/openecomp-sdc-enrichment-impl/src/main/java/org/openecomp/sdc/enrichment/impl/external/artifact/MonitoringMibEnricher.java
+++ b/openecomp-be/lib/openecomp-sdc-enrichment-lib/openecomp-sdc-enrichment-impl/src/main/java/org/openecomp/sdc/enrichment/impl/external/artifact/MonitoringMibEnricher.java
@@ -16,6 +16,19 @@
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()));
diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImpl.java b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImpl.java
index e112ef432c..22ac1e8ed8 100644
--- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImpl.java
+++ b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/main/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImpl.java
@@ -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));
}
/**
diff --git a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImplTest.java b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImplTest.java
index 04ddf6e2d4..c429709182 100644
--- a/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImplTest.java
+++ b/openecomp-be/lib/openecomp-sdc-externaltesting-lib/openecomp-sdc-externaltesting-impl/src/test/java/org/openecomp/core/externaltesting/impl/ExternalTestingManagerImplTest.java
@@ -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 {
diff --git a/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 b/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
index 3255e186e4..07dc53dfae 100644
--- a/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
+++ b/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
@@ -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];
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImpl.java b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImpl.java
index 14cf90a272..1bc547aed7 100644
--- a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImpl.java
+++ b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/services/impl/ToscaAnalyzerServiceImpl.java
@@ -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;
diff --git a/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/exportinfo/ExportDataCommand.java b/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/exportinfo/ExportDataCommand.java
index 5060f4bce2..2907d1e0cc 100644
--- a/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/exportinfo/ExportDataCommand.java
+++ b/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/exportinfo/ExportDataCommand.java
@@ -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());
}
diff --git a/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/importinfo/ImportDataCommand.java b/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/importinfo/ImportDataCommand.java
index 1f5281a66e..cff8eb98cf 100644
--- a/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/importinfo/ImportDataCommand.java
+++ b/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/importinfo/ImportDataCommand.java
@@ -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
index f58f18d93c..0000000000
--- a/openecomp-be/tools/zusammen-tools/src/main/java/org/openecomp/core/tools/util/ZipUtils.java
+++ /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.");
- }
- }
-}
-
diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/ToscaParserUtils.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/ToscaParserUtils.java
index be235d03ae..b7eaf99724 100644
--- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/ToscaParserUtils.java
+++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/ToscaParserUtils.java
@@ -20,29 +20,40 @@
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);
- }*/
-
-
}
diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/general/FileHandling.java b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/general/FileHandling.java
index 4dbc8b2dee..dae13a2c82 100644
--- a/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/general/FileHandling.java
+++ b/test-apis-ci/src/main/java/org/openecomp/sdc/ci/tests/utils/general/FileHandling.java
@@ -20,25 +20,33 @@
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;
diff --git a/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/DeploymentValiditaion.java b/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/DeploymentValiditaion.java
index fb60f44b64..de2b40868d 100644
--- a/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/DeploymentValiditaion.java
+++ b/test-apis-ci/src/main/java/org/openecomp/sdc/externalApis/DeploymentValiditaion.java
@@ -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{
diff --git a/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/utilities/FileHandling.java b/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/utilities/FileHandling.java
index 1ac4a72059..f8cc628d58 100644
--- a/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/utilities/FileHandling.java
+++ b/ui-ci/src/main/java/org/openecomp/sdc/ci/tests/utilities/FileHandling.java
@@ -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();
}