rApp package validation code refactor 52/12552/2
authoraravind.est <aravindhan.a@est.tech>
Tue, 20 Feb 2024 11:46:23 +0000 (11:46 +0000)
committeraravind.est <aravindhan.a@est.tech>
Wed, 21 Feb 2024 16:27:37 +0000 (16:27 +0000)
rApp package validation refactored.
Each validation condition should implement the interface RappValidator. It should throw respective error incase of the validation(RappValidationException) failure. Order should be defined for each validator. The validator gets evaluated based on the ascending order.

Issue-ID: NONRTRIC-984
Change-Id: I3309e714f26a1fdb5aa10b32c5a7113411dcdf4d
Signed-off-by: aravind.est <aravindhan.a@est.tech>
18 files changed:
rapp-manager-application/src/main/java/com/oransc/rappmanager/rest/RappController.java
rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandler.java
rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarPathProvider.java [new file with mode: 0755]
rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/ArtifactDefinitionValidator.java [new file with mode: 0755]
rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/FileExistenceValidator.java [new file with mode: 0755]
rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/NamingValidator.java [new file with mode: 0755]
rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidationHandler.java [new file with mode: 0755]
rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidationUtils.java [new file with mode: 0755]
rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidator.java [new file with mode: 0755]
rapp-manager-models/src/main/java/com/oransc/rappmanager/models/exception/ExceptionControllerHandler.java
rapp-manager-models/src/main/java/com/oransc/rappmanager/models/exception/RappHandlerException.java
rapp-manager-models/src/main/java/com/oransc/rappmanager/models/exception/RappValidationException.java [new file with mode: 0755]
rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/RappCsarConfigurationHandlerTest.java
rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/ArtifactDefinitionValidatorTest.java [new file with mode: 0755]
rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/FileExistenceValidatorTest.java [new file with mode: 0755]
rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/NamingValidatorTest.java [new file with mode: 0755]
rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/RappValidationHandlerTest.java [new file with mode: 0755]
rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/RappValidationUtilsTest.java [new file with mode: 0755]

index 287e297..85e1a44 100755 (executable)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START======================================================================
- * Copyright (C) 2023 Nordix Foundation. All rights reserved.
+ * Copyright (C) 2023-2024 Nordix Foundation. 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.
@@ -21,6 +21,7 @@ package com.oransc.rappmanager.rest;
 import com.oransc.rappmanager.configuration.RappManagerConfiguration;
 import com.oransc.rappmanager.models.cache.RappCacheService;
 import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler;
+import com.oransc.rappmanager.models.csar.validator.RappValidationHandler;
 import com.oransc.rappmanager.models.exception.RappHandlerException;
 import com.oransc.rappmanager.models.rapp.PrimeOrder;
 import com.oransc.rappmanager.models.rapp.Rapp;
@@ -56,6 +57,7 @@ public class RappController {
 
     Logger logger = LoggerFactory.getLogger(RappController.class);
     private final RappCsarConfigurationHandler rappCsarConfigurationHandler;
+    private final RappValidationHandler rappValidationHandler;
     private final RappManagerConfiguration rappManagerConfiguration;
     private final RappCacheService rappCacheService;
     private final RappService rappService;
@@ -75,7 +77,7 @@ public class RappController {
     @PostMapping("{rapp_id}")
     public ResponseEntity<Rapp> createRapp(@PathVariable("rapp_id") String rappId,
             @RequestPart("file") MultipartFile csarFilePart) throws IOException {
-        if (rappCsarConfigurationHandler.isValidRappPackage(csarFilePart)) {
+        if (rappValidationHandler.isValidRappPackage(csarFilePart)) {
             File csarFile = new File(
                     rappCsarConfigurationHandler.getRappPackageLocation(rappManagerConfiguration.getCsarLocation(),
                             rappId, csarFilePart.getOriginalFilename()).toUri());
index 9e2f953..41c0eaf 100755 (executable)
@@ -26,7 +26,6 @@ import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.gson.Gson;
-import com.oransc.rappmanager.models.exception.RappHandlerException;
 import com.oransc.rappmanager.models.rapp.Rapp;
 import com.oransc.rappmanager.models.rapp.RappResources;
 import com.oransc.rappmanager.models.rappinstance.RappACMInstance;
@@ -50,9 +49,7 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.core.io.ByteArrayResource;
-import org.springframework.http.HttpStatus;
 import org.springframework.stereotype.Service;
-import org.springframework.web.multipart.MultipartFile;
 import org.yaml.snakeyaml.Yaml;
 
 @Service
@@ -62,53 +59,14 @@ public class RappCsarConfigurationHandler {
     Logger logger = LoggerFactory.getLogger(RappCsarConfigurationHandler.class);
 
     private final ObjectMapper objectMapper;
-    private static final String TOSCA_METADATA_LOCATION = "TOSCA-Metadata/TOSCA.meta";
-    private static final String ENTRY_DEFINITIONS_INDEX = "Entry-Definitions";
-    private static final String ACM_COMPOSITION_JSON_LOCATION = "Files/Acm/definition/compositions.json";
-    private static final String ACM_DEFINITION_LOCATION = "Files/Acm/definition";
-    private static final String ACM_INSTANCES_LOCATION = "Files/Acm/instances";
-    private static final String SME_PROVIDER_FUNCS_LOCATION = "Files/Sme/providers";
-    private static final String SME_SERVICE_APIS_LOCATION = "Files/Sme/serviceapis";
-    private static final String SME_INVOKERS_LOCATION = "Files/Sme/invokers";
-    private static final String DME_PRODUCER_INFO_TYPES_LOCATION = "Files/Dme/producerinfotypes";
-    private static final String DME_CONSUMER_INFO_TYPES_LOCATION = "Files/Dme/consumerinfotypes";
-    private static final String DME_INFO_PRODUCERS_LOCATION = "Files/Dme/infoproducers";
-    private static final String DME_INFO_CONSUMERS_LOCATION = "Files/Dme/infoconsumers";
-    private static final String ARTIFACTS_LOCATION_JSON_POINTER =
-            "/topology_template/node_templates/applicationServiceDescriptor/artifacts";
-
-
-    public boolean isValidRappPackage(MultipartFile multipartFile) {
-        String originalFilename = multipartFile.getOriginalFilename();
-        if (originalFilename != null) {
-            return originalFilename.endsWith(".csar") && isFileExistsInCsar(multipartFile,
-                    ACM_COMPOSITION_JSON_LOCATION) && isFileExistsInCsar(multipartFile, TOSCA_METADATA_LOCATION)
-                           && containsValidArtifactDefinition(multipartFile);
-        }
-        return false;
-    }
-
-    boolean isFileExistsInCsar(MultipartFile multipartFile, String fileLocation) {
-        try (ZipArchiveInputStream zipArchiveInputStream = new ZipArchiveInputStream(multipartFile.getInputStream())) {
-            ArchiveEntry zipEntry;
-            while ((zipEntry = zipArchiveInputStream.getNextEntry()) != null) {
-                if (zipEntry.getName().matches(fileLocation)) {
-                    return Boolean.TRUE;
-                }
-            }
-            throw new RappHandlerException(HttpStatus.BAD_REQUEST, "rApp package missing a file " + fileLocation);
-        } catch (IOException e) {
-            logger.error("Unable to find the CSAR file", e);
-            throw new RappHandlerException(HttpStatus.BAD_REQUEST, "rApp package missing a file " + fileLocation);
-        }
-    }
 
     public Path getRappPackageLocation(String csarLocation, String rappId, String fileName) {
         return Path.of(csarLocation, rappId, fileName);
     }
 
     public String getInstantiationPayload(Rapp rapp, RappACMInstance rappACMInstance, UUID compositionId) {
-        return getPayload(rapp, getResourceUri(ACM_INSTANCES_LOCATION, rappACMInstance.getInstance())).replaceAll(
+        return getPayload(rapp,
+                getResourceUri(RappCsarPathProvider.ACM_INSTANCES_LOCATION, rappACMInstance.getInstance())).replaceAll(
                 "COMPOSITIONID", String.valueOf(compositionId));
     }
 
@@ -131,16 +89,6 @@ public class RappCsarConfigurationHandler {
                 getRappPackageLocation(rapp.getPackageLocation(), rapp.getName(), rapp.getPackageName()).toUri());
     }
 
-    ByteArrayOutputStream getFileFromCsar(MultipartFile multipartFile, String fileLocation) {
-        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
-        try (ZipArchiveInputStream zipArchiveInputStream = new ZipArchiveInputStream(multipartFile.getInputStream())) {
-            byteArrayOutputStream = getFileFromCsar(zipArchiveInputStream, fileLocation);
-        } catch (IOException e) {
-            logger.info("Unable to get file {} from the multipart CSAR file", fileLocation, e);
-        }
-        return byteArrayOutputStream;
-    }
-
     ByteArrayOutputStream getFileFromCsar(File csarFile, String fileLocation) {
         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
         try (FileInputStream fileInputStream = new FileInputStream(csarFile);
@@ -152,7 +100,7 @@ public class RappCsarConfigurationHandler {
         return byteArrayOutputStream;
     }
 
-    ByteArrayOutputStream getFileFromCsar(ZipArchiveInputStream zipArchiveInputStream, String fileLocation) {
+    public ByteArrayOutputStream getFileFromCsar(ZipArchiveInputStream zipArchiveInputStream, String fileLocation) {
         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
         try {
             ArchiveEntry entry;
@@ -171,44 +119,21 @@ public class RappCsarConfigurationHandler {
         return byteArrayOutputStream;
     }
 
-    boolean containsValidArtifactDefinition(MultipartFile multipartFile) {
-        String asdLocation = getAsdDefinitionLocation(multipartFile);
-        if (asdLocation != null && !asdLocation.isEmpty() && isFileExistsInCsar(multipartFile, asdLocation)) {
-            try {
-                String asdContent = getFileFromCsar(multipartFile, asdLocation).toString();
-                JsonNode jsonNode = getAsdContentNode(asdContent);
-                List<String> artifactFileList = jsonNode.at(ARTIFACTS_LOCATION_JSON_POINTER).findValuesAsText("file");
-                return artifactFileList.stream()
-                               .allMatch(artifactFile -> isFileExistsInCsar(multipartFile, artifactFile));
-            } catch (RappHandlerException e) {
-                throw e;
-            } catch (Exception e) {
-                logger.warn("Unable to validate artifact definition", e);
-                throw new RappHandlerException(HttpStatus.BAD_REQUEST, "ASD definition in rApp package is invalid.");
-            }
-        }
-        throw new RappHandlerException(HttpStatus.BAD_REQUEST, "ASD definition in rApp package is invalid.");
-    }
-
-    JsonNode getAsdContentNode(String asdContent) throws JsonProcessingException {
+    public JsonNode getAsdContentNode(String asdContent) throws JsonProcessingException {
         return objectMapper.readTree(new Gson().toJsonTree(new Yaml().load(asdContent)).toString());
     }
 
     String getAsdDefinitionLocation(final File csarFile) {
-        return getAsdDefinitionLocation(getFileFromCsar(csarFile, TOSCA_METADATA_LOCATION).toString());
+        return getAsdDefinitionLocation(
+                getFileFromCsar(csarFile, RappCsarPathProvider.TOSCA_METADATA_LOCATION).toString());
     }
 
-    String getAsdDefinitionLocation(final MultipartFile multipartFile) {
-        return getAsdDefinitionLocation(getFileFromCsar(multipartFile, TOSCA_METADATA_LOCATION).toString());
-    }
-
-    String getAsdDefinitionLocation(final String toscaMetadata) {
+    public String getAsdDefinitionLocation(final String toscaMetadata) {
         String asdLocation = "";
         if (toscaMetadata != null && !toscaMetadata.isEmpty()) {
-            final String entry =
-                    filter(on("\n").split(toscaMetadata), line -> line.contains(ENTRY_DEFINITIONS_INDEX)).iterator()
-                            .next();
-            asdLocation = entry.replace(ENTRY_DEFINITIONS_INDEX + ":", "").trim();
+            final String entry = filter(on("\n").split(toscaMetadata),
+                    line -> line.contains(RappCsarPathProvider.ENTRY_DEFINITIONS_INDEX)).iterator().next();
+            asdLocation = entry.replace(RappCsarPathProvider.ENTRY_DEFINITIONS_INDEX + ":", "").trim();
         }
         return asdLocation;
     }
@@ -221,7 +146,7 @@ public class RappCsarConfigurationHandler {
             try {
                 String asdContent = getFileFromCsar(csarFile, asdDefinitionLocation).toString();
                 JsonNode jsonNode = getAsdContentNode(asdContent);
-                JsonNode artifactsJsonNode = jsonNode.at(ARTIFACTS_LOCATION_JSON_POINTER);
+                JsonNode artifactsJsonNode = jsonNode.at(RappCsarPathProvider.ARTIFACTS_LOCATION_JSON_POINTER);
                 artifactsJsonNode.forEach(artifactJsonNode -> {
                     DeploymentItem deploymentItem =
                             objectMapper.convertValue(artifactJsonNode.at("/properties"), DeploymentItem.class);
@@ -237,36 +162,42 @@ public class RappCsarConfigurationHandler {
 
 
     public String getSmeProviderDomainPayload(Rapp rapp, RappSMEInstance rappSMEInstance) {
-        return getPayload(rapp, getResourceUri(SME_PROVIDER_FUNCS_LOCATION, rappSMEInstance.getProviderFunction()));
+        return getPayload(rapp, getResourceUri(RappCsarPathProvider.SME_PROVIDER_FUNCS_LOCATION,
+                rappSMEInstance.getProviderFunction()));
     }
 
     public String getSmeProviderApiPayload(Rapp rapp, RappSMEInstance rappSMEInstance) {
-        return getPayload(rapp, getResourceUri(SME_SERVICE_APIS_LOCATION, rappSMEInstance.getServiceApis()));
+        return getPayload(rapp,
+                getResourceUri(RappCsarPathProvider.SME_SERVICE_APIS_LOCATION, rappSMEInstance.getServiceApis()));
     }
 
     public String getSmeInvokerPayload(Rapp rapp, RappSMEInstance rappSMEInstance) {
-        return getPayload(rapp, getResourceUri(SME_INVOKERS_LOCATION, rappSMEInstance.getInvokers()));
+        return getPayload(rapp,
+                getResourceUri(RappCsarPathProvider.SME_INVOKERS_LOCATION, rappSMEInstance.getInvokers()));
     }
 
     public String getAcmCompositionPayload(Rapp rapp) {
-        return getPayload(rapp,
-                getResourceUri(ACM_DEFINITION_LOCATION, rapp.getRappResources().getAcm().getCompositionDefinitions()));
+        return getPayload(rapp, getResourceUri(RappCsarPathProvider.ACM_DEFINITION_LOCATION,
+                rapp.getRappResources().getAcm().getCompositionDefinitions()));
     }
 
     public String getDmeInfoProducerPayload(Rapp rapp, String producerIdentifier) {
-        return getPayload(rapp, getResourceUri(DME_INFO_PRODUCERS_LOCATION, producerIdentifier));
+        return getPayload(rapp, getResourceUri(RappCsarPathProvider.DME_INFO_PRODUCERS_LOCATION, producerIdentifier));
     }
 
     public String getDmeProducerInfoTypePayload(Rapp rapp, String infoTypeIdentifier) {
-        return getPayload(rapp, getResourceUri(DME_PRODUCER_INFO_TYPES_LOCATION, infoTypeIdentifier));
+        return getPayload(rapp,
+                getResourceUri(RappCsarPathProvider.DME_PRODUCER_INFO_TYPES_LOCATION, infoTypeIdentifier));
     }
 
     public String getDmeConsumerInfoTypePayload(Rapp rapp, String infoTypeIdentifier) {
-        return getPayload(rapp, getResourceUri(DME_CONSUMER_INFO_TYPES_LOCATION, infoTypeIdentifier));
+        return getPayload(rapp,
+                getResourceUri(RappCsarPathProvider.DME_CONSUMER_INFO_TYPES_LOCATION, infoTypeIdentifier));
     }
 
     public String getDmeInfoConsumerPayload(Rapp rapp, String infoConsumerIdentifier) {
-        return getPayload(rapp, getResourceUri(DME_INFO_CONSUMERS_LOCATION, infoConsumerIdentifier));
+        return getPayload(rapp,
+                getResourceUri(RappCsarPathProvider.DME_INFO_CONSUMERS_LOCATION, infoConsumerIdentifier));
     }
 
     String getResourceUri(String resourceLocation, String resource) {
@@ -279,17 +210,20 @@ public class RappCsarConfigurationHandler {
             File csarFile = getCsarFile(rapp);
             if (csarFile.exists()) {
                 rappResources.setAcm(RappResources.ACMResources.builder().compositionDefinitions(
-                        getFileListFromCsar(csarFile, ACM_DEFINITION_LOCATION).iterator().next()).compositionInstances(
-                        getFileListFromCsar(csarFile, ACM_INSTANCES_LOCATION)).build());
+                                getFileListFromCsar(csarFile, RappCsarPathProvider.ACM_DEFINITION_LOCATION).iterator().next())
+                                             .compositionInstances(getFileListFromCsar(csarFile,
+                                                     RappCsarPathProvider.ACM_INSTANCES_LOCATION)).build());
                 rappResources.setSme(RappResources.SMEResources.builder().providerFunctions(
-                                getFileListFromCsar(csarFile, SME_PROVIDER_FUNCS_LOCATION))
-                                             .serviceApis(getFileListFromCsar(csarFile, SME_SERVICE_APIS_LOCATION))
-                                             .invokers(getFileListFromCsar(csarFile, SME_INVOKERS_LOCATION)).build());
+                        getFileListFromCsar(csarFile, RappCsarPathProvider.SME_PROVIDER_FUNCS_LOCATION)).serviceApis(
+                        getFileListFromCsar(csarFile, RappCsarPathProvider.SME_SERVICE_APIS_LOCATION)).invokers(
+                        getFileListFromCsar(csarFile, RappCsarPathProvider.SME_INVOKERS_LOCATION)).build());
                 rappResources.setDme(RappResources.DMEResources.builder().producerInfoTypes(
-                                getFileListFromCsar(csarFile, DME_PRODUCER_INFO_TYPES_LOCATION)).consumerInfoTypes(
-                                getFileListFromCsar(csarFile, DME_CONSUMER_INFO_TYPES_LOCATION))
-                                             .infoProducers(getFileListFromCsar(csarFile, DME_INFO_PRODUCERS_LOCATION))
-                                             .infoConsumers(getFileListFromCsar(csarFile, DME_INFO_CONSUMERS_LOCATION))
+                                getFileListFromCsar(csarFile, RappCsarPathProvider.DME_PRODUCER_INFO_TYPES_LOCATION))
+                                             .consumerInfoTypes(getFileListFromCsar(csarFile,
+                                                     RappCsarPathProvider.DME_CONSUMER_INFO_TYPES_LOCATION))
+                                             .infoProducers(getFileListFromCsar(csarFile,
+                                                     RappCsarPathProvider.DME_INFO_PRODUCERS_LOCATION)).infoConsumers(
+                                getFileListFromCsar(csarFile, RappCsarPathProvider.DME_INFO_CONSUMERS_LOCATION))
                                              .build());
             }
         } catch (Exception e) {
diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarPathProvider.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/RappCsarPathProvider.java
new file mode 100755 (executable)
index 0000000..745ae14
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar;
+
+import lombok.experimental.UtilityClass;
+
+@UtilityClass
+public class RappCsarPathProvider {
+
+    public static final String TOSCA_METADATA_LOCATION = "TOSCA-Metadata/TOSCA.meta";
+    public static final String ENTRY_DEFINITIONS_INDEX = "Entry-Definitions";
+    public static final String ACM_COMPOSITION_JSON_LOCATION = "Files/Acm/definition/compositions.json";
+    public static final String ACM_DEFINITION_LOCATION = "Files/Acm/definition";
+    public static final String ACM_INSTANCES_LOCATION = "Files/Acm/instances";
+    public static final String SME_PROVIDER_FUNCS_LOCATION = "Files/Sme/providers";
+    public static final String SME_SERVICE_APIS_LOCATION = "Files/Sme/serviceapis";
+    public static final String SME_INVOKERS_LOCATION = "Files/Sme/invokers";
+    public static final String DME_PRODUCER_INFO_TYPES_LOCATION = "Files/Dme/producerinfotypes";
+    public static final String DME_CONSUMER_INFO_TYPES_LOCATION = "Files/Dme/consumerinfotypes";
+    public static final String DME_INFO_PRODUCERS_LOCATION = "Files/Dme/infoproducers";
+    public static final String DME_INFO_CONSUMERS_LOCATION = "Files/Dme/infoconsumers";
+    public static final String ARTIFACTS_LOCATION_JSON_POINTER =
+            "/topology_template/node_templates/applicationServiceDescriptor/artifacts";
+}
\ No newline at end of file
diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/ArtifactDefinitionValidator.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/ArtifactDefinitionValidator.java
new file mode 100755 (executable)
index 0000000..ac00e95
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler;
+import com.oransc.rappmanager.models.csar.RappCsarPathProvider;
+import com.oransc.rappmanager.models.exception.RappValidationException;
+import java.util.List;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+import org.springframework.validation.Errors;
+import org.springframework.web.multipart.MultipartFile;
+
+@Component
+@RequiredArgsConstructor
+public class ArtifactDefinitionValidator implements RappValidator {
+
+    private final RappCsarConfigurationHandler rappCsarConfigurationHandler;
+    private final RappValidationUtils rappValidationUtils;
+    String invalidAsdErrorMsg = "ASD definition in rApp package is invalid.";
+    private static final int VALIDATION_ORDER = 10;
+
+    @Override
+    public int getOrder() {
+        return VALIDATION_ORDER;
+    }
+
+    @Override
+    public void validate(Object target, Errors errors) {
+        MultipartFile multipartFile = (MultipartFile) target;
+        String asdLocation = rappValidationUtils.getAsdDefinitionLocation(multipartFile);
+        if (asdLocation != null && !asdLocation.isEmpty() && rappValidationUtils.isFileExistsInCsar(multipartFile,
+                asdLocation)) {
+            try {
+                String asdContent = rappValidationUtils.getFileFromCsar(multipartFile, asdLocation).toString();
+                if(asdContent != null && !asdContent.isEmpty()) {
+                    JsonNode jsonNode = rappCsarConfigurationHandler.getAsdContentNode(asdContent);
+                    List<String> artifactFileList =
+                            jsonNode.at(RappCsarPathProvider.ARTIFACTS_LOCATION_JSON_POINTER).findValuesAsText("file");
+                    artifactFileList.forEach(
+                            artifactFile -> rappValidationUtils.isFileExistsInCsar(multipartFile, artifactFile));
+                } else {
+                    throw new RappValidationException(invalidAsdErrorMsg);
+                }
+            } catch (RappValidationException e) {
+                throw new RappValidationException(e.getMessage());
+            } catch (Exception e) {
+                throw new RappValidationException(invalidAsdErrorMsg);
+            }
+        } else {
+            throw new RappValidationException(invalidAsdErrorMsg);
+        }
+    }
+}
diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/FileExistenceValidator.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/FileExistenceValidator.java
new file mode 100755 (executable)
index 0000000..3ed6124
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator;
+
+import com.oransc.rappmanager.models.csar.RappCsarPathProvider;
+import java.util.List;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+import org.springframework.validation.Errors;
+import org.springframework.web.multipart.MultipartFile;
+
+@Component
+@RequiredArgsConstructor
+public class FileExistenceValidator implements RappValidator {
+
+    private final RappValidationUtils rappValidationUtils;
+    private final List<String> requiredFiles =
+            List.of(RappCsarPathProvider.ACM_COMPOSITION_JSON_LOCATION, RappCsarPathProvider.TOSCA_METADATA_LOCATION);
+    private static final int VALIDATION_ORDER = 5;
+
+    @Override
+    public int getOrder() {
+        return VALIDATION_ORDER;
+    }
+
+    @Override
+    public void validate(Object target, Errors errors) {
+        MultipartFile multipartFile = (MultipartFile) target;
+        requiredFiles.forEach(requiredFile -> rappValidationUtils.isFileExistsInCsar(multipartFile, requiredFile));
+    }
+}
diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/NamingValidator.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/NamingValidator.java
new file mode 100755 (executable)
index 0000000..00348af
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator;
+
+import com.oransc.rappmanager.models.exception.RappValidationException;
+import org.springframework.stereotype.Component;
+import org.springframework.validation.Errors;
+import org.springframework.web.multipart.MultipartFile;
+
+@Component
+public class NamingValidator implements RappValidator {
+
+    private static final int VALIDATION_ORDER = 1;
+
+    @Override
+    public int getOrder() {
+        return VALIDATION_ORDER;
+    }
+
+    @Override
+    public void validate(Object target, Errors errors) {
+        MultipartFile multipartFile = (MultipartFile) target;
+        String originalFilename = multipartFile.getOriginalFilename();
+        if (originalFilename == null || !originalFilename.endsWith(".csar")) {
+            throw new RappValidationException("rApp package name should end with .csar");
+        }
+    }
+}
diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidationHandler.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidationHandler.java
new file mode 100755 (executable)
index 0000000..8df2154
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator;
+
+import java.util.Comparator;
+import java.util.List;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+@Component
+@RequiredArgsConstructor
+public class RappValidationHandler {
+
+    private final List<RappValidator> rappValidators;
+
+    public boolean isValidRappPackage(MultipartFile multipartFile) {
+        List<RappValidator> validatorList =
+                rappValidators.stream().sorted(Comparator.comparing(RappValidator::getOrder)).toList();
+        validatorList.forEach(rappValidator -> rappValidator.validate(multipartFile, null));
+        return true;
+    }
+}
diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidationUtils.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidationUtils.java
new file mode 100755 (executable)
index 0000000..29be2d3
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator;
+
+import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler;
+import com.oransc.rappmanager.models.csar.RappCsarPathProvider;
+import com.oransc.rappmanager.models.exception.RappValidationException;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.compress.archivers.ArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+@Component
+@RequiredArgsConstructor
+public class RappValidationUtils {
+
+    private final RappCsarConfigurationHandler rappCsarConfigurationHandler;
+
+    boolean isFileExistsInCsar(MultipartFile multipartFile, String fileLocation) {
+        try (ZipArchiveInputStream zipArchiveInputStream = new ZipArchiveInputStream(multipartFile.getInputStream())) {
+            ArchiveEntry zipEntry;
+            while ((zipEntry = zipArchiveInputStream.getNextEntry()) != null) {
+                if (zipEntry.getName().matches(fileLocation)) {
+                    return Boolean.TRUE;
+                }
+            }
+            throw new RappValidationException("rApp package missing a file " + fileLocation);
+        } catch (IOException e) {
+            throw new RappValidationException("rApp package missing a file " + fileLocation);
+        }
+    }
+
+    public String getAsdDefinitionLocation(final MultipartFile multipartFile) {
+        return rappCsarConfigurationHandler.getAsdDefinitionLocation(
+                getFileFromCsar(multipartFile, RappCsarPathProvider.TOSCA_METADATA_LOCATION).toString());
+    }
+
+    ByteArrayOutputStream getFileFromCsar(MultipartFile multipartFile, String fileLocation) {
+        ByteArrayOutputStream byteArrayOutputStream;
+        try (ZipArchiveInputStream zipArchiveInputStream = new ZipArchiveInputStream(multipartFile.getInputStream())) {
+            byteArrayOutputStream = rappCsarConfigurationHandler.getFileFromCsar(zipArchiveInputStream, fileLocation);
+        } catch (IOException e) {
+            throw new RappValidationException(
+                    String.format("Unable to get file %s from the multipart CSAR file", fileLocation));
+        }
+        return byteArrayOutputStream;
+    }
+}
\ No newline at end of file
diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidator.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/csar/validator/RappValidator.java
new file mode 100755 (executable)
index 0000000..a1f3930
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator;
+
+import org.springframework.validation.Validator;
+import org.springframework.web.multipart.MultipartFile;
+
+public interface RappValidator extends Validator {
+    int getOrder();
+    @Override
+    default boolean supports(Class<?> cls) {
+        return MultipartFile.class.isAssignableFrom(cls);
+    }
+}
index 40af0d3..ae26a5e 100755 (executable)
@@ -1,6 +1,6 @@
 /*
  * ============LICENSE_START======================================================================
- * Copyright (C) 2023 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2023-2024 OpenInfra Foundation Europe. 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.
@@ -30,4 +30,11 @@ public class ExceptionControllerHandler {
         return ResponseEntity.status(rappHandlerException.getStatusCode())
                        .body(new ErrorResponse(rappHandlerException.getMessage()));
     }
+
+    @ExceptionHandler(RappValidationException.class)
+    public ResponseEntity<ErrorResponse> handleRappValidationException(
+            RappValidationException rappValidationException) {
+        return ResponseEntity.status(rappValidationException.getStatusCode())
+                       .body(new ErrorResponse(rappValidationException.getMessage()));
+    }
 }
index 8ea89be..48b5067 100755 (executable)
@@ -1,6 +1,6 @@
 /*
  * ============LICENSE_START======================================================================
- * Copyright (C) 2023 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2023-2024 OpenInfra Foundation Europe. 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.
@@ -29,7 +29,5 @@ public class RappHandlerException extends RuntimeException {
     public RappHandlerException(HttpStatusCode statusCode, String message) {
         super(message);
         this.statusCode = statusCode;
-
     }
-
 }
diff --git a/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/exception/RappValidationException.java b/rapp-manager-models/src/main/java/com/oransc/rappmanager/models/exception/RappValidationException.java
new file mode 100755 (executable)
index 0000000..f8c291c
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.exception;
+
+import lombok.Getter;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.HttpStatusCode;
+
+@Getter
+public class RappValidationException extends RuntimeException {
+
+    private final HttpStatusCode statusCode;
+
+    public RappValidationException(String message) {
+        super(message);
+        this.statusCode = HttpStatus.BAD_REQUEST;
+    }
+}
index e769b12..2325789 100755 (executable)
@@ -23,18 +23,12 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.gson.JsonSyntaxException;
-import com.oransc.rappmanager.models.exception.RappHandlerException;
 import com.oransc.rappmanager.models.rapp.Rapp;
 import com.oransc.rappmanager.models.rapp.RappResources;
 import com.oransc.rappmanager.models.rappinstance.RappACMInstance;
@@ -42,26 +36,17 @@ import com.oransc.rappmanager.models.rappinstance.RappDMEInstance;
 import com.oransc.rappmanager.models.rappinstance.RappSMEInstance;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
 import java.util.List;
 import java.util.Set;
 import java.util.UUID;
-import java.util.stream.Stream;
-import org.apache.http.entity.ContentType;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.MethodSource;
 import org.junit.jupiter.params.provider.ValueSource;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.mock.mockito.SpyBean;
-import org.springframework.http.HttpStatus;
-import org.springframework.mock.web.MockMultipartFile;
 import org.springframework.test.context.ContextConfiguration;
-import org.springframework.web.multipart.MultipartFile;
 
 @SpringBootTest
 @ContextConfiguration(classes = {ObjectMapper.class, RappCsarConfigurationHandler.class})
@@ -74,123 +59,10 @@ class RappCsarConfigurationHandlerTest {
 
     private final String validRappFile = "valid-rapp-package.csar";
 
-    private final String invalidRappFile = "invalid-rapp-package.csar";
-
     private final String invalidRappNoAsdFile = "invalid-rapp-package-no-asd-yaml.csar";
 
     private final String invalidRappEmptyAsdFile = "invalid-rapp-package-empty-asd-yaml.csar";
 
-    @Test
-    void testCsarPackageValidationSuccess() throws IOException {
-        String rappCsarPath = validCsarFileLocation + File.separator + validRappFile;
-        MultipartFile multipartFile =
-                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
-                        new FileInputStream(rappCsarPath));
-        assertEquals(Boolean.TRUE, rappCsarConfigurationHandler.isValidRappPackage(multipartFile));
-    }
-
-    @ParameterizedTest
-    @MethodSource("getInvalidCsarPackage")
-    void testCsarPackageValidationFailure(MultipartFile multipartFile) {
-        RappHandlerException exception = assertThrows(RappHandlerException.class,
-                () -> rappCsarConfigurationHandler.isValidRappPackage(multipartFile));
-        assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode());
-    }
-
-
-    private static Stream<Arguments> getInvalidCsarPackage() throws IOException {
-        String validCsarFileLocation = "src/test/resources";
-        String rappCsarPath = validCsarFileLocation + File.separator + "invalid-rapp-package.csar";
-        MultipartFile multipartFile =
-                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
-                        new FileInputStream(rappCsarPath));
-        String rappCsarPathNoTosca = validCsarFileLocation + File.separator + "invalid-rapp-package-no-tosca.csar";
-        MultipartFile multipartFileNoTosca = new MockMultipartFile(rappCsarPathNoTosca, rappCsarPathNoTosca,
-                ContentType.MULTIPART_FORM_DATA.getMimeType(), new FileInputStream(rappCsarPathNoTosca));
-        String rappCsarPathNoAsdYaml = validCsarFileLocation + File.separator + "invalid-rapp-package-no-asd-yaml.csar";
-        MultipartFile multipartFileNoAsdYaml = new MockMultipartFile(rappCsarPathNoAsdYaml, rappCsarPathNoAsdYaml,
-                ContentType.MULTIPART_FORM_DATA.getMimeType(), new FileInputStream(rappCsarPathNoAsdYaml));
-        String rappCsarPathMissingArtifact =
-                validCsarFileLocation + File.separator + "invalid-rapp-package-missing-artifact.csar";
-        MultipartFile multipartFileMissingArtifact =
-                new MockMultipartFile(rappCsarPathMissingArtifact, rappCsarPathMissingArtifact,
-                        ContentType.MULTIPART_FORM_DATA.getMimeType(),
-                        new FileInputStream(rappCsarPathMissingArtifact));
-        String rappCsarPathNoComposition =
-                validCsarFileLocation + File.separator + "invalid-rapp-package-no-acm-composition.csar";
-        MultipartFile multipartFileNoComposition =
-                new MockMultipartFile(rappCsarPathNoComposition, rappCsarPathNoComposition,
-                        ContentType.MULTIPART_FORM_DATA.getMimeType(), new FileInputStream(rappCsarPathNoComposition));
-        return Stream.of(Arguments.of(multipartFile), Arguments.of(multipartFileNoTosca),
-                Arguments.of(multipartFileNoAsdYaml), Arguments.of(multipartFileMissingArtifact),
-                Arguments.of(multipartFileNoComposition));
-    }
-
-    @Test
-    void testCsarPackageValidationFailureWithoutOrginalName() {
-        MultipartFile multipartFile = mock(MultipartFile.class);
-        assertEquals(Boolean.FALSE, rappCsarConfigurationHandler.isValidRappPackage(multipartFile));
-    }
-
-    @Test
-    void testInvalidCsarFileExist() {
-        MultipartFile multipartFile = mock(MultipartFile.class);
-        RappHandlerException exception = assertThrows(RappHandlerException.class,
-                () -> rappCsarConfigurationHandler.isFileExistsInCsar(multipartFile, "INVALID_LOCATION"));
-        assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode());
-    }
-
-    @Test
-    void testCsarContainsValidAsdFile() throws IOException {
-        String rappCsarPath = validCsarFileLocation + File.separator + validRappFile;
-        MultipartFile multipartFile =
-                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
-                        new FileInputStream(rappCsarPath));
-        assertTrue(rappCsarConfigurationHandler.containsValidArtifactDefinition(multipartFile));
-    }
-
-    @Test
-    void testCsarContainsValidAsdFileFailure() throws IOException {
-        String rappCsarPath = validCsarFileLocation + File.separator + invalidRappFile;
-        MultipartFile multipartFile =
-                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
-                        new FileInputStream(rappCsarPath));
-        RappHandlerException exception = assertThrows(RappHandlerException.class,
-                () -> rappCsarConfigurationHandler.containsValidArtifactDefinition(multipartFile));
-        assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode());
-    }
-
-    @Test
-    void testCsarNoAsdFailure() {
-        MultipartFile multipartFile = mock(MultipartFile.class);
-        RappHandlerException exception = assertThrows(RappHandlerException.class,
-                () -> rappCsarConfigurationHandler.containsValidArtifactDefinition(multipartFile));
-        assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode());
-    }
-
-    @Test
-    void testCsarAsdContentInvalidFailure() throws IOException {
-        String rappCsarPath = validCsarFileLocation + File.separator + validRappFile;
-        MultipartFile multipartFile =
-                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
-                        new FileInputStream(rappCsarPath));
-        String invalidJson = "{asasdasd";
-        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
-        byteArrayOutputStream.write(invalidJson.getBytes(), 0, invalidJson.getBytes().length);
-        doCallRealMethod().doReturn(byteArrayOutputStream).when(rappCsarConfigurationHandler)
-                .getFileFromCsar(any(MultipartFile.class), any());
-        RappHandlerException exception = assertThrows(RappHandlerException.class,
-                () -> rappCsarConfigurationHandler.containsValidArtifactDefinition(multipartFile));
-        assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode());
-    }
-
-    @Test
-    void testgetFileFromCsarFailure() throws IOException {
-        MultipartFile multipartFile = mock(MultipartFile.class);
-        when(multipartFile.getInputStream()).thenThrow(new IOException());
-        assertThat(rappCsarConfigurationHandler.getFileFromCsar(multipartFile, null).size()).isZero();
-    }
-
     @Test
     void testCsarInstantiationPayload() throws JSONException {
         Rapp rapp = Rapp.builder().name("").packageName(validRappFile).packageLocation(validCsarFileLocation).build();
diff --git a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/ArtifactDefinitionValidatorTest.java b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/ArtifactDefinitionValidatorTest.java
new file mode 100755 (executable)
index 0000000..7348116
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler;
+import com.oransc.rappmanager.models.exception.RappValidationException;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import org.apache.http.entity.ContentType;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.NullSource;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.SpyBean;
+import org.springframework.http.HttpStatus;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.web.multipart.MultipartFile;
+
+@SpringBootTest
+@ContextConfiguration(classes = {ArtifactDefinitionValidator.class, RappValidationUtils.class, ObjectMapper.class,
+        RappCsarConfigurationHandler.class})
+class ArtifactDefinitionValidatorTest {
+
+    @Autowired
+    ArtifactDefinitionValidator artifactDefinitionValidator;
+    @SpyBean
+    RappValidationUtils rappValidationUtils;
+    String validCsarFileLocation = "src/test/resources/";
+    String validRappFile = "valid-rapp-package.csar";
+    String invalidRappFile = "invalid-rapp-package.csar";
+    String invalidRappAsdEmptyFile = "invalid-rapp-package-empty-asd-yaml.csar";
+
+    @Test
+    void testCsarContainsValidAsdFile() throws IOException {
+        String rappCsarPath = validCsarFileLocation + File.separator + validRappFile;
+        MultipartFile multipartFile =
+                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
+                        new FileInputStream(rappCsarPath));
+        assertDoesNotThrow(() -> artifactDefinitionValidator.validate(multipartFile, null));
+    }
+
+    @Test
+    void testCsarContainsValidAsdFileFailure() throws IOException {
+        String rappCsarPath = validCsarFileLocation + File.separator + invalidRappFile;
+        MultipartFile multipartFile =
+                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
+                        new FileInputStream(rappCsarPath));
+        RappValidationException exception = assertThrows(RappValidationException.class,
+                () -> artifactDefinitionValidator.validate(multipartFile, null));
+        assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode());
+        assertTrue(exception.getMessage().startsWith("rApp package missing a file"));
+    }
+
+    @Test
+    void testCsarNoAsdFailure() {
+        MultipartFile multipartFile = mock(MultipartFile.class);
+        RappValidationException exception = assertThrows(RappValidationException.class,
+                () -> artifactDefinitionValidator.validate(multipartFile, null));
+        assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode());
+        assertEquals("ASD definition in rApp package is invalid.", exception.getMessage());
+    }
+
+    @ParameterizedTest
+    @NullSource
+    @ValueSource(strings = {""})
+    void testCsarAsdLocationNullFailure(String asdLocation) throws IOException {
+        String rappCsarPath = validCsarFileLocation + File.separator + invalidRappAsdEmptyFile;
+        MultipartFile multipartFile =
+                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
+                        new FileInputStream(rappCsarPath));
+        doReturn(asdLocation).when(rappValidationUtils).getAsdDefinitionLocation(any());
+        RappValidationException exception = assertThrows(RappValidationException.class,
+                () -> artifactDefinitionValidator.validate(multipartFile, null));
+        assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode());
+        assertEquals("ASD definition in rApp package is invalid.", exception.getMessage());
+    }
+
+    @ParameterizedTest
+    @NullSource
+    @ValueSource(strings = {"", "{asasdasd"})
+    void testCsarAsdContentInvalidFailure(String asdContent) throws IOException {
+        String rappCsarPath = validCsarFileLocation + File.separator + validRappFile;
+        MultipartFile multipartFile =
+                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
+                        new FileInputStream(rappCsarPath));
+        if (asdContent != null) {
+            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+            byteArrayOutputStream.write(asdContent.getBytes(), 0, asdContent.getBytes().length);
+            doCallRealMethod().doReturn(byteArrayOutputStream).when(rappValidationUtils)
+                    .getFileFromCsar(any(MultipartFile.class), any());
+        } else {
+            doCallRealMethod().doReturn(asdContent).when(rappValidationUtils)
+                    .getFileFromCsar(any(MultipartFile.class), any());
+        }
+        RappValidationException exception = assertThrows(RappValidationException.class,
+                () -> artifactDefinitionValidator.validate(multipartFile, null));
+        assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode());
+        assertEquals("ASD definition in rApp package is invalid.", exception.getMessage());
+    }
+}
diff --git a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/FileExistenceValidatorTest.java b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/FileExistenceValidatorTest.java
new file mode 100755 (executable)
index 0000000..2b6e369
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator;
+
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler;
+import com.oransc.rappmanager.models.exception.RappValidationException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import org.apache.http.entity.ContentType;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.HttpStatus;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.web.multipart.MultipartFile;
+
+@SpringBootTest
+@ContextConfiguration(classes = {FileExistenceValidator.class, RappValidationUtils.class, ObjectMapper.class,
+        RappCsarConfigurationHandler.class})
+class FileExistenceValidatorTest {
+
+    @Autowired
+    FileExistenceValidator fileExistenceValidator;
+    String validCsarFileLocation = "src/test/resources/";
+    String validRappFile = "valid-rapp-package.csar";
+    String invalidRappFile = "invalid-rapp-package.csar";
+    String invalidRappFileNoTosca = "invalid-rapp-package-no-tosca.csar";
+
+    @Test
+    void testFileExistenceValidationSuccess() throws IOException {
+        String rappCsarPath = validCsarFileLocation + File.separator + validRappFile;
+        MultipartFile multipartFile =
+                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
+                        new FileInputStream(rappCsarPath));
+        assertDoesNotThrow(() -> fileExistenceValidator.validate(multipartFile, null));
+    }
+
+    @Test
+    void testFileExistenceNoCompositionValidation() throws IOException {
+        String rappCsarPath = validCsarFileLocation + File.separator + invalidRappFile;
+        MultipartFile multipartFile =
+                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
+                        new FileInputStream(rappCsarPath));
+        RappValidationException rappValidationException =
+                assertThrows(RappValidationException.class, () -> fileExistenceValidator.validate(multipartFile, null));
+        assertEquals(HttpStatus.BAD_REQUEST, rappValidationException.getStatusCode());
+        assertEquals("rApp package missing a file Files/Acm/definition/compositions.json",
+                rappValidationException.getMessage());
+    }
+
+    @Test
+    void testFileExistenceNoToscaValidation() throws IOException {
+        String rappCsarPath = validCsarFileLocation + File.separator + invalidRappFileNoTosca;
+        MultipartFile multipartFile =
+                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
+                        new FileInputStream(rappCsarPath));
+        RappValidationException rappValidationException =
+                assertThrows(RappValidationException.class, () -> fileExistenceValidator.validate(multipartFile, null));
+        assertEquals(HttpStatus.BAD_REQUEST, rappValidationException.getStatusCode());
+        assertEquals("rApp package missing a file TOSCA-Metadata/TOSCA.meta", rappValidationException.getMessage());
+    }
+}
diff --git a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/NamingValidatorTest.java b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/NamingValidatorTest.java
new file mode 100755 (executable)
index 0000000..e059cf3
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.oransc.rappmanager.models.exception.RappValidationException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import org.apache.http.entity.ContentType;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.HttpStatus;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.web.multipart.MultipartFile;
+
+@SpringBootTest
+@ContextConfiguration(classes = {NamingValidator.class})
+class NamingValidatorTest {
+
+    @Autowired
+    NamingValidator namingValidator;
+    String validCsarFileLocation = "src/test/resources/";
+    String validRappFile = "valid-rapp-package.csar";
+    String expectedErrorMessage = "rApp package name should end with .csar";
+
+    @Test
+    void testNamingValidationSuccess() throws IOException {
+        String rappCsarPath = validCsarFileLocation + File.separator + validRappFile;
+        MultipartFile multipartFile =
+                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
+                        new FileInputStream(rappCsarPath));
+        assertDoesNotThrow(() -> namingValidator.validate(multipartFile, null));
+    }
+
+    @Test
+    void testNamingValidationFailureWithNull() {
+        MultipartFile multipartFile = mock(MultipartFile.class);
+        RappValidationException rappValidationException =
+                assertThrows(RappValidationException.class, () -> namingValidator.validate(multipartFile, null));
+        assertEquals(HttpStatus.BAD_REQUEST, rappValidationException.getStatusCode());
+        assertEquals(expectedErrorMessage, rappValidationException.getMessage());
+    }
+
+    @Test
+    void testNamingValidationFailureWithEmptyName() {
+        MultipartFile multipartFile = mock(MultipartFile.class);
+        when(multipartFile.getOriginalFilename()).thenReturn("");
+        RappValidationException rappValidationException =
+                assertThrows(RappValidationException.class, () -> namingValidator.validate(multipartFile, null));
+        assertEquals(HttpStatus.BAD_REQUEST, rappValidationException.getStatusCode());
+        assertEquals(expectedErrorMessage, rappValidationException.getMessage());
+    }
+}
diff --git a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/RappValidationHandlerTest.java b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/RappValidationHandlerTest.java
new file mode 100755 (executable)
index 0000000..9edfe34
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.mock;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler;
+import com.oransc.rappmanager.models.exception.RappValidationException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.stream.Stream;
+import org.apache.http.entity.ContentType;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.HttpStatus;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.web.multipart.MultipartFile;
+
+@SpringBootTest
+@ContextConfiguration(classes = {RappValidationHandler.class, NamingValidator.class, FileExistenceValidator.class,
+        ArtifactDefinitionValidator.class, RappValidationUtils.class, RappCsarConfigurationHandler.class,
+        ObjectMapper.class})
+class RappValidationHandlerTest {
+
+    @Autowired
+    RappValidationHandler rappValidationHandler;
+    String validCsarFileLocation = "src/test/resources/";
+    private final String validRappFile = "valid-rapp-package.csar";
+
+    @Test
+    void testCsarPackageValidationSuccess() throws IOException {
+        String rappCsarPath = validCsarFileLocation + File.separator + validRappFile;
+        MultipartFile multipartFile =
+                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
+                        new FileInputStream(rappCsarPath));
+        assertEquals(Boolean.TRUE, rappValidationHandler.isValidRappPackage(multipartFile));
+    }
+
+    @ParameterizedTest
+    @MethodSource("getInvalidCsarPackage")
+    void testCsarPackageValidationFailure(MultipartFile multipartFile, String errorMessage) {
+        RappValidationException exception = assertThrows(RappValidationException.class,
+                () -> rappValidationHandler.isValidRappPackage(multipartFile));
+        assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode());
+        assertEquals(errorMessage, exception.getMessage());
+    }
+
+    private static Stream<Arguments> getInvalidCsarPackage() throws IOException {
+        String validCsarFileLocation = "src/test/resources";
+        String errorMsgMissingAcmComposition = "rApp package missing a file Files/Acm/definition/compositions.json";
+        String rappCsarPath = validCsarFileLocation + File.separator + "invalid-rapp-package.csar";
+        MultipartFile multipartFile =
+                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
+                        new FileInputStream(rappCsarPath));
+        String rappCsarPathNoTosca = validCsarFileLocation + File.separator + "invalid-rapp-package-no-tosca.csar";
+        MultipartFile multipartFileNoTosca = new MockMultipartFile(rappCsarPathNoTosca, rappCsarPathNoTosca,
+                ContentType.MULTIPART_FORM_DATA.getMimeType(), new FileInputStream(rappCsarPathNoTosca));
+        String rappCsarPathNoAsdYaml = validCsarFileLocation + File.separator + "invalid-rapp-package-no-asd-yaml.csar";
+        MultipartFile multipartFileNoAsdYaml = new MockMultipartFile(rappCsarPathNoAsdYaml, rappCsarPathNoAsdYaml,
+                ContentType.MULTIPART_FORM_DATA.getMimeType(), new FileInputStream(rappCsarPathNoAsdYaml));
+        String rappCsarPathMissingArtifact =
+                validCsarFileLocation + File.separator + "invalid-rapp-package-missing-artifact.csar";
+        MultipartFile multipartFileMissingArtifact =
+                new MockMultipartFile(rappCsarPathMissingArtifact, rappCsarPathMissingArtifact,
+                        ContentType.MULTIPART_FORM_DATA.getMimeType(),
+                        new FileInputStream(rappCsarPathMissingArtifact));
+        String rappCsarPathNoComposition =
+                validCsarFileLocation + File.separator + "invalid-rapp-package-no-acm-composition.csar";
+        MultipartFile multipartFileNoComposition =
+                new MockMultipartFile(rappCsarPathNoComposition, rappCsarPathNoComposition,
+                        ContentType.MULTIPART_FORM_DATA.getMimeType(), new FileInputStream(rappCsarPathNoComposition));
+        return Stream.of(Arguments.of(multipartFile, errorMsgMissingAcmComposition),
+                Arguments.of(multipartFileNoTosca, "rApp package missing a file TOSCA-Metadata/TOSCA.meta"),
+                Arguments.of(multipartFileNoAsdYaml, "rApp package missing a file Definitions/asd.yaml"),
+                Arguments.of(multipartFileMissingArtifact,
+                        "rApp package missing a file Artifacts/Deployment/HELM/orufhrecovery-1.0.0.tgz"),
+                Arguments.of(multipartFileNoComposition, errorMsgMissingAcmComposition));
+    }
+
+    @Test
+    void testCsarPackageValidationFailureWithoutOrginalName() {
+        MultipartFile multipartFile = mock(MultipartFile.class);
+        RappValidationException exception = assertThrows(RappValidationException.class,
+                () -> rappValidationHandler.isValidRappPackage(multipartFile));
+        assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode());
+        assertEquals("rApp package name should end with .csar", exception.getMessage());
+    }
+}
diff --git a/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/RappValidationUtilsTest.java b/rapp-manager-models/src/test/java/com/oransc/rappmanager/models/csar/validator/RappValidationUtilsTest.java
new file mode 100755 (executable)
index 0000000..7f1d8de
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * ============LICENSE_START======================================================================
+ * Copyright (C) 2024 OpenInfra Foundation Europe. 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 com.oransc.rappmanager.models.csar.validator;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler;
+import com.oransc.rappmanager.models.csar.RappCsarPathProvider;
+import com.oransc.rappmanager.models.exception.RappValidationException;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import org.apache.http.entity.ContentType;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.HttpStatus;
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.web.multipart.MultipartFile;
+
+@SpringBootTest
+@ContextConfiguration(classes = {RappValidationUtils.class, ObjectMapper.class, RappCsarConfigurationHandler.class})
+class RappValidationUtilsTest {
+
+    String validCsarFileLocation = "src/test/resources/";
+    private final String validRappFile = "valid-rapp-package.csar";
+    private final String invalidRappNoToscaFile = "invalid-rapp-package-no-tosca.csar";
+    @Autowired
+    RappValidationUtils rappValidationUtils;
+
+    @Test
+    void testCsarFileExist() throws IOException {
+        String rappCsarPath = validCsarFileLocation + File.separator + validRappFile;
+        MultipartFile multipartFile =
+                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
+                        new FileInputStream(rappCsarPath));
+        assertTrue(rappValidationUtils.isFileExistsInCsar(multipartFile, RappCsarPathProvider.TOSCA_METADATA_LOCATION));
+
+    }
+
+    @Test
+    void testInvalidCsarFileExist() {
+        MultipartFile multipartFile = mock(MultipartFile.class);
+        RappValidationException exception = assertThrows(RappValidationException.class,
+                () -> rappValidationUtils.isFileExistsInCsar(multipartFile, "INVALID_LOCATION"));
+        assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode());
+        assertEquals("rApp package missing a file INVALID_LOCATION", exception.getMessage());
+    }
+
+    @Test
+    void testGetFileFromCsar() throws IOException {
+        String rappCsarPath = validCsarFileLocation + File.separator + validRappFile;
+        MultipartFile multipartFile =
+                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
+                        new FileInputStream(rappCsarPath));
+        assertNotNull(rappValidationUtils.getFileFromCsar(multipartFile, RappCsarPathProvider.TOSCA_METADATA_LOCATION));
+    }
+
+    @Test
+    void testGetFileFromCsarFailure() throws IOException {
+        MultipartFile multipartFile = mock(MultipartFile.class);
+        when(multipartFile.getInputStream()).thenThrow(new IOException());
+        RappValidationException exception = assertThrows(RappValidationException.class,
+                () -> rappValidationUtils.getFileFromCsar(multipartFile, null));
+        assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode());
+        assertEquals(String.format("Unable to get file %s from the multipart CSAR file", null), exception.getMessage());
+    }
+
+    @Test
+    void testGetAsdLocationCsar() throws IOException {
+        String rappCsarPath = validCsarFileLocation + File.separator + validRappFile;
+        MultipartFile multipartFile =
+                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
+                        new FileInputStream(rappCsarPath));
+        assertEquals("Definitions/asd.yaml", rappValidationUtils.getAsdDefinitionLocation(multipartFile));
+    }
+
+    @Test
+    void testGetAsdLocationCsarFailure() throws IOException {
+        String rappCsarPath = validCsarFileLocation + File.separator + invalidRappNoToscaFile;
+        MultipartFile multipartFile =
+                new MockMultipartFile(rappCsarPath, rappCsarPath, ContentType.MULTIPART_FORM_DATA.getMimeType(),
+                        new FileInputStream(rappCsarPath));
+        assertEquals("", rappValidationUtils.getAsdDefinitionLocation(multipartFile));
+    }
+}