Fix and refactor manifest parsing 91/95391/4
authorandre.schmid <andre.schmid@est.tech>
Fri, 30 Aug 2019 17:20:32 +0000 (18:20 +0100)
committerOren Kleks <orenkle@amdocs.com>
Thu, 24 Oct 2019 06:15:28 +0000 (06:15 +0000)
Fix a CMS signature reading expected token.
Fix the necessity of a empty line in the end of the manifest.
Implement CMS signature, Source checksum algorithm and digest reading.
Indicate the line number and content when a manifest error occurs.
Remove unnecessary recursive reading.
Centralize manifest tokens.
Improve tests by checking the expected error.
Document the code.

Change-Id: I7d12020d8922fc5d4c8d9f238557dfbcc0b65757
Issue-ID: SDC-2563
Signed-off-by: andre.schmid <andre.schmid@est.tech>
44 files changed:
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/ManifestBuilder.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/ManifestBuilderTest.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/ONAPCsarValidatorTest.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/SOL004MetaDirectoryValidatorTest.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/impl/orchestration/csar/validation/ValidatorFactoryTest.java
openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/test/java/org/openecomp/sdc/vendorsoftwareproduct/upload/csar/UploadCSARFileTest.java
openecomp-be/lib/openecomp-common-lib/src/main/java/org/openecomp/sdc/common/errors/Messages.java
openecomp-be/lib/openecomp-sdc-validation-lib/openecomp-sdc-validation-api/src/main/java/org/openecomp/core/validation/errors/ErrorMessagesFormatBuilder.java
openecomp-be/lib/openecomp-tosca-lib/pom.xml
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/AbstractOnboardingManifest.java
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/AlgorithmDigest.java [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/CSARConstants.java
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/Manifest.java
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/ManifestTokenType.java [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/ONAPManifestOnboarding.java
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/OnboardingToscaMetadata.java
openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/SOL004ManifestOnboarding.java
openecomp-be/lib/openecomp-tosca-lib/src/test/java/org/openecomp/sdc/tosca/csar/ManifestParsingTest.java [deleted file]
openecomp-be/lib/openecomp-tosca-lib/src/test/java/org/openecomp/sdc/tosca/csar/SOL004ManifestOnboardingTest.java [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/InValidNonManoTosca.mf
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/InvalidTosca2.mf
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/InvalidTosca3.mf
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/InvalidToscaNonManoGarbageAtEnd.mf [moved from openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/InvalidTocsaNonManoGarbadgeAtEnd.mf with 90% similarity]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/ValidNonManoTosca.mf
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/ValidTosca.mf
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/double-signed.mf [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/empty-manifest.mf [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/empty-metadata-with-source.mf [moved from openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/InvalidTosca4.mf with 100% similarity]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/empty-metadata.mf [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/metadata-duplicated-entries.mf [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/metadata-incorrect-entry.mf [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/metadata-mixed-entries.mf [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/metadata-no-entry.mf [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/metadata-no-value.mf [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/no-metadata.mf [moved from openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/InvalidTosca1.mf with 100% similarity]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/non-mano-key-with-empty-source.mf [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/non-mano-key-with-no-sources.mf [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/source-algorithm-without-hash.mf [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/source-algorithm-without-value.mf [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/source-hash-without-algorithm.mf [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/source-hash-without-value.mf [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/valid/metadata-pnfd.mf [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/valid/signed-with-non-mano.mf [new file with mode: 0644]
openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/valid/signed.mf [new file with mode: 0644]

index c7fd225..eff1fb3 100644 (file)
 
 package org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation;
 
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.ALGORITHM;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.HASH;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.METADATA;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.NON_MANO_ARTIFACT_SETS;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.SOURCE;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.TreeMap;
-import org.openecomp.sdc.tosca.csar.CSARConstants;
 
 /**
  * Builds SOL0004 manifest file as a String.
@@ -73,8 +78,8 @@ public class ManifestBuilder {
      */
     public ManifestBuilder withSignedSource(final String sourcePath, final String hashAlgorithm, final String hash) {
         TreeMap<String, String> sourcePropertiesMap = new TreeMap<>();
-        sourcePropertiesMap.put(CSARConstants.ALGORITHM_MF_ATTRIBUTE, hashAlgorithm);
-        sourcePropertiesMap.put(CSARConstants.HASH_MF_ATTRIBUTE, hash);
+        sourcePropertiesMap.put(ALGORITHM.getToken(), hashAlgorithm);
+        sourcePropertiesMap.put(HASH.getToken(), hash);
         sourceWithPropertiesMap.put(sourcePath, sourcePropertiesMap);
         return this;
     }
@@ -119,7 +124,7 @@ public class ManifestBuilder {
 
     private String buildMetadata() {
         final StringBuilder stringBuilder = new StringBuilder();
-        stringBuilder.append(String.format(SECTION_FORMAT, CSARConstants.METADATA_MF_ATTRIBUTE));
+        stringBuilder.append(String.format(SECTION_FORMAT, METADATA.getToken()));
         for (Entry<String, String> metadataAndValue : metadataMap.entrySet()) {
             stringBuilder.append("\t");
             stringBuilder.append(String.format(PROPERTY_FORMAT, metadataAndValue.getKey(), metadataAndValue.getValue()));
@@ -131,17 +136,17 @@ public class ManifestBuilder {
     private String buildSource() {
         final StringBuilder stringBuilder = new StringBuilder();
         for (final Entry<String, Map<String, String>> signedSourceMap : sourceWithPropertiesMap.entrySet()) {
-            stringBuilder.append(String.format(PROPERTY_FORMAT, CSARConstants.SOURCE_MF_ATTRIBUTE, signedSourceMap.getKey()));
+            stringBuilder.append(String.format(PROPERTY_FORMAT, SOURCE.getToken(), signedSourceMap.getKey()));
             final Map<String, String> propertiesMap = signedSourceMap.getValue();
             if (propertiesMap != null && !propertiesMap.isEmpty()) {
-                final String algorithm = propertiesMap.get(CSARConstants.ALGORITHM_MF_ATTRIBUTE);
+                final String algorithm = propertiesMap.get(ALGORITHM.getToken());
                 if (algorithm != null) {
-                    stringBuilder.append(String.format(PROPERTY_FORMAT, CSARConstants.ALGORITHM_MF_ATTRIBUTE, algorithm));
+                    stringBuilder.append(String.format(PROPERTY_FORMAT, ALGORITHM.getToken(), algorithm));
                 }
 
-                final String hash = propertiesMap.get(CSARConstants.HASH_MF_ATTRIBUTE);
+                final String hash = propertiesMap.get(HASH.getToken());
                 if (hash != null) {
-                    stringBuilder.append(String.format(PROPERTY_FORMAT, CSARConstants.HASH_MF_ATTRIBUTE, hash));
+                    stringBuilder.append(String.format(PROPERTY_FORMAT, HASH.getToken(), hash));
                 }
             }
         }
@@ -151,13 +156,13 @@ public class ManifestBuilder {
 
     private String buildNonManoArtifact() {
         final StringBuilder stringBuilder = new StringBuilder();
-        stringBuilder.append(String.format(SECTION_FORMAT, CSARConstants.NON_MANO_MF_ATTRIBUTE));
+        stringBuilder.append(String.format(SECTION_FORMAT, NON_MANO_ARTIFACT_SETS.getToken()));
         for (Entry<String, List<String>> artifactTypeAndSourcesEntry : nonManoArtifactMap.entrySet()) {
             stringBuilder.append("\t");
             stringBuilder.append(String.format(SECTION_FORMAT, artifactTypeAndSourcesEntry.getKey()));
             for (String source : artifactTypeAndSourcesEntry.getValue()) {
                 stringBuilder.append("\t\t");
-                stringBuilder.append(String.format(PROPERTY_FORMAT, CSARConstants.SOURCE_MF_ATTRIBUTE, source));
+                stringBuilder.append(String.format(PROPERTY_FORMAT, SOURCE.getToken(), source));
             }
         }
         return stringBuilder.toString();
index e022e2f..5079ecc 100644 (file)
@@ -24,6 +24,10 @@ import static org.hamcrest.Matchers.hasItems;
 import static org.hamcrest.Matchers.hasSize;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.isEmptyString;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.PNFD_ARCHIVE_VERSION;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.PNFD_NAME;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.PNFD_PROVIDER;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.PNFD_RELEASE_DATE_TIME;
 import static org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation.NonManoArtifactType.ONAP_PM_DICTIONARY;
 import static org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation.NonManoArtifactType.ONAP_VES_EVENTS;
 
@@ -34,7 +38,6 @@ import java.util.Map;
 import java.util.TreeMap;
 import org.junit.Before;
 import org.junit.Test;
-import org.openecomp.sdc.tosca.csar.CSARConstants;
 import org.openecomp.sdc.tosca.csar.Manifest;
 import org.openecomp.sdc.tosca.csar.SOL004ManifestOnboarding;
 
@@ -92,10 +95,10 @@ public class ManifestBuilderTest {
     @Test
     public void givenMetadata_whenBuildingManifestWithMetadata_thenParsedManifestMetadataShouldBeTheSame() {
         final Map<String, String> expectedMetadataMap = new TreeMap<>();
-        expectedMetadataMap.put(CSARConstants.PNFD_NAME, "myPnf");
-        expectedMetadataMap.put(CSARConstants.PNFD_PROVIDER, "Acme");
-        expectedMetadataMap.put(CSARConstants.PNFD_ARCHIVE_VERSION, "1.0");
-        expectedMetadataMap.put(CSARConstants.PNFD_RELEASE_DATE_TIME, "2019-03-11T11:25:00+00:00");
+        expectedMetadataMap.put(PNFD_NAME.getToken(), "myPnf");
+        expectedMetadataMap.put(PNFD_PROVIDER.getToken(), "Acme");
+        expectedMetadataMap.put(PNFD_ARCHIVE_VERSION.getToken(), "1.0");
+        expectedMetadataMap.put(PNFD_RELEASE_DATE_TIME.getToken(), "2019-03-11T11:25:00+00:00");
 
         expectedMetadataMap.forEach((key, value) -> manifestBuilder.withMetaData(key, value));
 
@@ -150,7 +153,10 @@ public class ManifestBuilderTest {
     }
 
     private void mockManifestMetadata() {
-        manifestBuilder.withMetaData(CSARConstants.PNFD_PROVIDER, "test");
+        manifestBuilder.withMetaData(PNFD_PROVIDER.getToken(), "provider");
+        manifestBuilder.withMetaData(PNFD_NAME.getToken(), "name");
+        manifestBuilder.withMetaData(PNFD_RELEASE_DATE_TIME.getToken(), "datetime");
+        manifestBuilder.withMetaData(PNFD_ARCHIVE_VERSION.getToken(), "1.0");
     }
 
     private void mockManifestSource() {
index 76a31b2..6dc8e1a 100644 (file)
@@ -30,12 +30,12 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
 
 
 public class ONAPCsarValidatorTest {
 
-    ONAPCsarValidator onapCsarValidator;
+    private ONAPCsarValidator onapCsarValidator;
     private FileContentHandler contentHandler;
     private List<String> folderList;
 
@@ -85,9 +85,9 @@ public class ONAPCsarValidatorTest {
     private void assertExpectedErrors( String testCase, Map<String, List<ErrorMessage>> errors, int expectedErrors){
         if(expectedErrors > 0){
             List<ErrorMessage> errorMessages = errors.get(SdcCommon.UPLOAD_FILE);
-            assertTrue(testCase, errorMessages.size() == expectedErrors);
+            assertEquals(testCase, expectedErrors, errorMessages.size());
         }else{
-            assertTrue(testCase,errors.size() == expectedErrors);
+            assertEquals(testCase, expectedErrors, errors.size());
         }
     }
 }
index 328f00c..2e0fd86 100644 (file)
 
 package org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation;
 
-import org.apache.commons.collections.CollectionUtils;
-import org.junit.Before;
-import org.junit.Test;
-import org.openecomp.core.utilities.file.FileContentHandler;
-import org.openecomp.sdc.common.errors.Messages;
-import org.openecomp.sdc.common.utils.SdcCommon;
-import org.openecomp.sdc.datatypes.error.ErrorLevel;
-import org.openecomp.sdc.datatypes.error.ErrorMessage;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import org.openecomp.sdc.logging.api.Logger;
-import org.openecomp.sdc.logging.api.LoggerFactory;
-
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.hasSize;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.hamcrest.Matchers.containsInAnyOrder;
-import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.PNFD_NAME;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.PNFD_PROVIDER;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.PNFD_ARCHIVE_VERSION;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.PNFD_RELEASE_DATE_TIME;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.SEPARATOR_MF_ATTRIBUTE;
 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ENTRY_DEFINITIONS;
 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ETSI_ENTRY_CERTIFICATE;
 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ETSI_ENTRY_CHANGE_LOG;
@@ -56,14 +34,42 @@ import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ETSI_ENTRY_L
 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ETSI_ENTRY_MANIFEST;
 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ETSI_ENTRY_TESTS;
 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_PATH_FILE_NAME;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.VNF_PRODUCT_NAME;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.VNF_PROVIDER_ID;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.VNF_PACKAGE_VERSION;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.VNF_RELEASE_DATE_TIME;
-
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.ATTRIBUTE_VALUE_SEPARATOR;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.PNFD_ARCHIVE_VERSION;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.PNFD_NAME;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.PNFD_RELEASE_DATE_TIME;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNF_PACKAGE_VERSION;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNF_PRODUCT_NAME;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNF_PROVIDER_ID;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNF_RELEASE_DATE_TIME;
 import static org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation.NonManoArtifactType.ONAP_PM_DICTIONARY;
 import static org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation.NonManoArtifactType.ONAP_VES_EVENTS;
-import static org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation.TestConstants.*;
+import static org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation.TestConstants.EMPTY_YAML_FILE_PATH;
+import static org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation.TestConstants.INVALID_YAML_FILE_PATH;
+import static org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation.TestConstants.SAMPLE_DEFINITION_FILE_PATH;
+import static org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation.TestConstants.SAMPLE_DEFINITION_IMPORT_FILE_PATH;
+import static org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation.TestConstants.SAMPLE_SOURCE;
+import static org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation.TestConstants.TOSCA_CHANGELOG_FILEPATH;
+import static org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation.TestConstants.TOSCA_DEFINITION_FILEPATH;
+import static org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation.TestConstants.TOSCA_MANIFEST_FILEPATH;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.collections.CollectionUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.openecomp.core.utilities.file.FileContentHandler;
+import org.openecomp.sdc.common.errors.Messages;
+import org.openecomp.sdc.common.utils.SdcCommon;
+import org.openecomp.sdc.datatypes.error.ErrorLevel;
+import org.openecomp.sdc.datatypes.error.ErrorMessage;
+import org.openecomp.sdc.logging.api.Logger;
+import org.openecomp.sdc.logging.api.LoggerFactory;
+import org.openecomp.sdc.tosca.csar.ManifestTokenType;
 
 public class SOL004MetaDirectoryValidatorTest {
 
@@ -81,9 +87,9 @@ public class SOL004MetaDirectoryValidatorTest {
                 "TOSCA-Meta-File-Version: 1.0\n"+
                 "CSAR-Version: 1.1\n"+
                 "Created-By: Vendor\n"+
-                TOSCA_META_ENTRY_DEFINITIONS + SEPARATOR_MF_ATTRIBUTE + "Definitions/MainServiceTemplate.yaml\n"+
-                TOSCA_META_ETSI_ENTRY_MANIFEST + SEPARATOR_MF_ATTRIBUTE + "Definitions/MainServiceTemplate.mf\n"+
-                TOSCA_META_ETSI_ENTRY_CHANGE_LOG + SEPARATOR_MF_ATTRIBUTE + "Artifacts/changeLog.text\n";
+                TOSCA_META_ENTRY_DEFINITIONS + ATTRIBUTE_VALUE_SEPARATOR.getToken() + "Definitions/MainServiceTemplate.yaml\n"+
+                TOSCA_META_ETSI_ENTRY_MANIFEST + ATTRIBUTE_VALUE_SEPARATOR.getToken() + "Definitions/MainServiceTemplate.mf\n"+
+                TOSCA_META_ETSI_ENTRY_CHANGE_LOG + ATTRIBUTE_VALUE_SEPARATOR.getToken() + "Artifacts/changeLog.text\n";
     }
 
     @Test
@@ -92,7 +98,7 @@ public class SOL004MetaDirectoryValidatorTest {
                 "Entry-Definitions: Definitions/MainServiceTemplate.yaml";
 
         handler.addFile(TOSCA_META_PATH_FILE_NAME, metaFileWithInvalidEntry.getBytes(StandardCharsets.UTF_8));
-        handler.addFile(TOSCA_DEFINITION_FILEPATH, getResourceBytes(TestConstants.SAMPLE_DEFINITION_FILE_PATH));
+        handler.addFile(TOSCA_DEFINITION_FILEPATH, getResourceBytes(SAMPLE_DEFINITION_FILE_PATH));
 
         final Map<String, List<ErrorMessage>> errors = sol004MetaDirectoryValidator.validateContent(handler, Collections.emptyList());
         assertExpectedErrors("TOSCA Meta file with no entries", errors, 1);
@@ -109,8 +115,8 @@ public class SOL004MetaDirectoryValidatorTest {
         folderList.add("Files/Licenses/");
 
         metaFile = metaFile +
-                TOSCA_META_ETSI_ENTRY_TESTS + SEPARATOR_MF_ATTRIBUTE + entryTestFilePath + "\n" +
-                TOSCA_META_ETSI_ENTRY_LICENSES + SEPARATOR_MF_ATTRIBUTE + entryLicenseFilePath +"\n";
+                TOSCA_META_ETSI_ENTRY_TESTS + ATTRIBUTE_VALUE_SEPARATOR.getToken() + entryTestFilePath + "\n" +
+                TOSCA_META_ETSI_ENTRY_LICENSES + ATTRIBUTE_VALUE_SEPARATOR.getToken() + entryLicenseFilePath +"\n";
 
         handler.addFile(TOSCA_META_PATH_FILE_NAME, metaFile.getBytes(StandardCharsets.UTF_8));
         handler.addFile(TOSCA_DEFINITION_FILEPATH, getResourceBytes(SAMPLE_DEFINITION_FILE_PATH));
@@ -156,16 +162,16 @@ public class SOL004MetaDirectoryValidatorTest {
                 "TOSCA-Meta-File-Version: " + Integer.MAX_VALUE +
                 "\nCSAR-Version: " + Integer.MAX_VALUE  +
                 "\nCreated-By: Bilal Iqbal\n" +
-                TOSCA_META_ENTRY_DEFINITIONS+ SEPARATOR_MF_ATTRIBUTE + "Definitions/MainServiceTemplate.yaml\n" +
-                TOSCA_META_ETSI_ENTRY_MANIFEST + SEPARATOR_MF_ATTRIBUTE + "Definitions/MainServiceTemplate.mf\n"+
-                TOSCA_META_ETSI_ENTRY_CHANGE_LOG + SEPARATOR_MF_ATTRIBUTE + "Artifacts/changeLog.text";
+                TOSCA_META_ENTRY_DEFINITIONS + ATTRIBUTE_VALUE_SEPARATOR.getToken() + "Definitions/MainServiceTemplate.yaml\n" +
+                TOSCA_META_ETSI_ENTRY_MANIFEST + ATTRIBUTE_VALUE_SEPARATOR.getToken() + "Definitions/MainServiceTemplate.mf\n"+
+                TOSCA_META_ETSI_ENTRY_CHANGE_LOG + ATTRIBUTE_VALUE_SEPARATOR.getToken() + "Artifacts/changeLog.text";
 
         final ManifestBuilder manifestBuilder = getVnfManifestSampleBuilder();
 
         handler.addFile(TOSCA_META_PATH_FILE_NAME, metaFile.getBytes(StandardCharsets.UTF_8));
         manifestBuilder.withSource(TOSCA_META_PATH_FILE_NAME);
 
-        handler.addFile(TOSCA_DEFINITION_FILEPATH, getResourceBytes(TestConstants.SAMPLE_DEFINITION_FILE_PATH));
+        handler.addFile(TOSCA_DEFINITION_FILEPATH, getResourceBytes(SAMPLE_DEFINITION_FILE_PATH));
         manifestBuilder.withSource(TOSCA_DEFINITION_FILEPATH);
 
         handler.addFile(TOSCA_CHANGELOG_FILEPATH, "".getBytes(StandardCharsets.UTF_8));
@@ -437,9 +443,9 @@ public class SOL004MetaDirectoryValidatorTest {
                 "TOSCA-Meta-File-Version: 1.0\n"+
                 "CSAR-Version: 1.1\n"+
                 "Created-By: Vendor\n"+
-                TOSCA_META_ENTRY_DEFINITIONS + SEPARATOR_MF_ATTRIBUTE + "Definitions/MainServiceTemplate.yaml\n"+
-                TOSCA_META_ETSI_ENTRY_MANIFEST + SEPARATOR_MF_ATTRIBUTE +"Definitions/MainServiceTemplate2.mf\n"+
-                TOSCA_META_ETSI_ENTRY_CHANGE_LOG + SEPARATOR_MF_ATTRIBUTE +"Artifacts/changeLog.text\n";
+                TOSCA_META_ENTRY_DEFINITIONS + ATTRIBUTE_VALUE_SEPARATOR.getToken() + "Definitions/MainServiceTemplate.yaml\n"+
+                TOSCA_META_ETSI_ENTRY_MANIFEST + ATTRIBUTE_VALUE_SEPARATOR.getToken() +"Definitions/MainServiceTemplate2.mf\n"+
+                TOSCA_META_ETSI_ENTRY_CHANGE_LOG + ATTRIBUTE_VALUE_SEPARATOR.getToken() +"Artifacts/changeLog.text\n";
 
         final ManifestBuilder manifestBuilder = getVnfManifestSampleBuilder();
 
@@ -470,8 +476,8 @@ public class SOL004MetaDirectoryValidatorTest {
                 "CSAR-Version: 1.1\n"+
                 "Created-By: Vendor\n"+
                 "Entry-Definitions: Definitions/MainServiceTemplate.yaml\n"+
-                TOSCA_META_ETSI_ENTRY_MANIFEST + SEPARATOR_MF_ATTRIBUTE +  "Definitions/MainServiceTemplate.txt\n"+
-                TOSCA_META_ETSI_ENTRY_CHANGE_LOG + SEPARATOR_MF_ATTRIBUTE + "Artifacts/changeLog.text\n";
+                TOSCA_META_ETSI_ENTRY_MANIFEST + ATTRIBUTE_VALUE_SEPARATOR.getToken() +  "Definitions/MainServiceTemplate.txt\n"+
+                TOSCA_META_ETSI_ENTRY_CHANGE_LOG + ATTRIBUTE_VALUE_SEPARATOR.getToken() + "Artifacts/changeLog.text\n";
 
         final ManifestBuilder manifestBuilder = getVnfManifestSampleBuilder();
 
@@ -540,10 +546,10 @@ public class SOL004MetaDirectoryValidatorTest {
     @Test
     public void testGivenManifestFile_withMetadataContainingMixedPnfVnfMetadata_thenErrorIsReturned() {
         final ManifestBuilder manifestBuilder = new ManifestBuilder()
-            .withMetaData(PNFD_NAME, "RadioNode")
-            .withMetaData(VNF_PROVIDER_ID, "Bilal Iqbal")
-            .withMetaData(PNFD_ARCHIVE_VERSION, "1.0")
-            .withMetaData(VNF_RELEASE_DATE_TIME, "2019-12-14T11:25:00+00:00");
+            .withMetaData(PNFD_NAME.getToken(), "RadioNode")
+            .withMetaData(VNF_PROVIDER_ID.getToken(), "Bilal Iqbal")
+            .withMetaData(PNFD_ARCHIVE_VERSION.getToken(), "1.0")
+            .withMetaData(VNF_RELEASE_DATE_TIME.getToken(), "2019-12-14T11:25:00+00:00");
 
         handler.addFile(TOSCA_META_PATH_FILE_NAME, metaFile.getBytes(StandardCharsets.UTF_8));
         manifestBuilder.withSource(TOSCA_META_PATH_FILE_NAME);
@@ -588,8 +594,8 @@ public class SOL004MetaDirectoryValidatorTest {
     public void testGivenManifestFile_withMetadataMissingMandatoryPnfEntries_thenErrorIsReturned() {
         final ManifestBuilder manifestBuilder = new ManifestBuilder();
 
-        manifestBuilder.withMetaData(PNFD_NAME, "RadioNode");
-        manifestBuilder.withMetaData(PNFD_RELEASE_DATE_TIME, "2019-12-14T11:25:00+00:00");
+        manifestBuilder.withMetaData(PNFD_NAME.getToken(), "RadioNode");
+        manifestBuilder.withMetaData(PNFD_RELEASE_DATE_TIME.getToken(), "2019-12-14T11:25:00+00:00");
 
         handler.addFile(TOSCA_META_PATH_FILE_NAME, metaFile.getBytes(StandardCharsets.UTF_8));
         manifestBuilder.withSource(TOSCA_META_PATH_FILE_NAME);
@@ -604,7 +610,7 @@ public class SOL004MetaDirectoryValidatorTest {
         handler.addFile(TOSCA_MANIFEST_FILEPATH, manifestBuilder.build().getBytes(StandardCharsets.UTF_8));
 
         final Map<String, List<ErrorMessage>> errors = sol004MetaDirectoryValidator.validateContent(handler, Collections.emptyList());
-        assertExpectedErrors("Manifest with metadata missing pnf mandatory entries should return error", errors, 3);
+        assertExpectedErrors("Manifest with metadata missing pnf mandatory entries should return error", errors, 1);
 
     }
 
@@ -612,7 +618,7 @@ public class SOL004MetaDirectoryValidatorTest {
     public void testGivenManifestFile_withMetadataMissingMandatoryVnfEntries_thenErrorIsReturned() {
         final ManifestBuilder manifestBuilder = new ManifestBuilder();
 
-        manifestBuilder.withMetaData(VNF_PRODUCT_NAME, "RadioNode");
+        manifestBuilder.withMetaData(VNF_PRODUCT_NAME.getToken(), "RadioNode");
 
         handler.addFile(TOSCA_META_PATH_FILE_NAME, metaFile.getBytes(StandardCharsets.UTF_8));
         manifestBuilder.withSource(TOSCA_META_PATH_FILE_NAME);
@@ -627,7 +633,7 @@ public class SOL004MetaDirectoryValidatorTest {
         handler.addFile(TOSCA_MANIFEST_FILEPATH, manifestBuilder.build().getBytes(StandardCharsets.UTF_8));
 
         final Map<String, List<ErrorMessage>> errors = sol004MetaDirectoryValidator.validateContent(handler, Collections.emptyList());
-        assertExpectedErrors("Manifest with metadata missing vnf mandatory entries should return error", errors, 4);
+        assertExpectedErrors("Manifest with metadata missing vnf mandatory entries should return error", errors, 1);
 
     }
 
@@ -637,10 +643,10 @@ public class SOL004MetaDirectoryValidatorTest {
     @Test
     public void testGivenManifestFile_withMetadataEntriesExceedingTheLimit_thenErrorIsReturned() {
         final ManifestBuilder manifestBuilder = getVnfManifestSampleBuilder()
-            .withMetaData(PNFD_NAME, "RadioNode")
-            .withMetaData(PNFD_PROVIDER, "Bilal Iqbal")
-            .withMetaData(PNFD_ARCHIVE_VERSION, "1.0")
-            .withMetaData(PNFD_RELEASE_DATE_TIME, "2019-03-11T11:25:00+00:00");
+            .withMetaData(PNFD_NAME.getToken(), "RadioNode")
+            .withMetaData(ManifestTokenType.PNFD_PROVIDER.getToken(), "Bilal Iqbal")
+            .withMetaData(PNFD_ARCHIVE_VERSION.getToken(), "1.0")
+            .withMetaData(PNFD_RELEASE_DATE_TIME.getToken(), "2019-03-11T11:25:00+00:00");
 
         handler.addFile(TOSCA_META_PATH_FILE_NAME, metaFile.getBytes(StandardCharsets.UTF_8));
         manifestBuilder.withSource(TOSCA_META_PATH_FILE_NAME);
@@ -655,7 +661,7 @@ public class SOL004MetaDirectoryValidatorTest {
         handler.addFile(TOSCA_MANIFEST_FILEPATH, manifestBuilder.build().getBytes(StandardCharsets.UTF_8));
 
         final Map<String, List<ErrorMessage>> errors = sol004MetaDirectoryValidator.validateContent(handler, Collections.emptyList());
-        assertExpectedErrors("Manifest with more than 4 metadata entries should return error", errors, 2);
+        assertExpectedErrors("Manifest with more than 4 metadata entries should return error", errors, 1);
     }
 
     @Test
@@ -663,9 +669,9 @@ public class SOL004MetaDirectoryValidatorTest {
         final ManifestBuilder manifestBuilder = getPnfManifestSampleBuilder();
 
         metaFile = metaFile +
-            TOSCA_META_ETSI_ENTRY_TESTS + SEPARATOR_MF_ATTRIBUTE + "Files/Tests\n" +
-            TOSCA_META_ETSI_ENTRY_LICENSES + SEPARATOR_MF_ATTRIBUTE + "Files/Licenses\n" +
-            TOSCA_META_ETSI_ENTRY_CERTIFICATE + SEPARATOR_MF_ATTRIBUTE + "Files/Certificates";
+            TOSCA_META_ETSI_ENTRY_TESTS + ATTRIBUTE_VALUE_SEPARATOR.getToken() + "Files/Tests\n" +
+            TOSCA_META_ETSI_ENTRY_LICENSES + ATTRIBUTE_VALUE_SEPARATOR.getToken() + "Files/Licenses\n" +
+            TOSCA_META_ETSI_ENTRY_CERTIFICATE + ATTRIBUTE_VALUE_SEPARATOR.getToken() + "Files/Certificates";
 
         handler.addFile(TOSCA_META_PATH_FILE_NAME, metaFile.getBytes(StandardCharsets.UTF_8));
         manifestBuilder.withSource(TOSCA_META_PATH_FILE_NAME);
@@ -908,9 +914,9 @@ public class SOL004MetaDirectoryValidatorTest {
         final List<ErrorMessage> errorMessages = errors.get(SdcCommon.UPLOAD_FILE);
         printErrorMessages(errorMessages);
         if (expectedErrors > 0) {
-            assertEquals(testCase, errorMessages.size(), expectedErrors);
+            assertEquals(testCase, expectedErrors, errorMessages.size());
         } else {
-            assertEquals(testCase, errors.size(), expectedErrors);
+            assertEquals(testCase, expectedErrors, errors.size());
         }
     }
 
@@ -936,18 +942,18 @@ public class SOL004MetaDirectoryValidatorTest {
 
     private ManifestBuilder getPnfManifestSampleBuilder() {
         return new ManifestBuilder()
-            .withMetaData(PNFD_NAME, "myPnf")
-            .withMetaData(PNFD_PROVIDER, "ACME")
-            .withMetaData(PNFD_ARCHIVE_VERSION, "1.0")
-            .withMetaData(PNFD_RELEASE_DATE_TIME, "2019-03-11T11:25:00+00:00");
+            .withMetaData(PNFD_NAME.getToken(), "myPnf")
+            .withMetaData(ManifestTokenType.PNFD_PROVIDER.getToken(), "ACME")
+            .withMetaData(PNFD_ARCHIVE_VERSION.getToken(), "1.0")
+            .withMetaData(PNFD_RELEASE_DATE_TIME.getToken(), "2019-03-11T11:25:00+00:00");
     }
 
     private ManifestBuilder getVnfManifestSampleBuilder() {
         return new ManifestBuilder()
-            .withMetaData(VNF_PRODUCT_NAME, "RadioNode")
-            .withMetaData(VNF_PROVIDER_ID, "ACME")
-            .withMetaData(VNF_PACKAGE_VERSION, "1.0")
-            .withMetaData(VNF_RELEASE_DATE_TIME, "2019-03-11T11:25:00+00:00");
+            .withMetaData(VNF_PRODUCT_NAME.getToken(), "RadioNode")
+            .withMetaData(VNF_PROVIDER_ID.getToken(), "ACME")
+            .withMetaData(VNF_PACKAGE_VERSION.getToken(), "1.0")
+            .withMetaData(VNF_RELEASE_DATE_TIME.getToken(), "2019-03-11T11:25:00+00:00");
     }
 
     private void assertExpectedErrors(List<ErrorMessage> actualErrorList, final List<ErrorMessage> expectedErrorList) {
index d9fca4d..344fe8b 100644 (file)
@@ -27,11 +27,11 @@ import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 
 import static org.junit.Assert.assertEquals;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.SEPARATOR_MF_ATTRIBUTE;
 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ENTRY_DEFINITIONS;
 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ETSI_ENTRY_CHANGE_LOG;
 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ETSI_ENTRY_MANIFEST;
 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_PATH_FILE_NAME;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.ATTRIBUTE_VALUE_SEPARATOR;
 import static org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation.TestConstants.TOSCA_CHANGELOG_FILEPATH;
 import static org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation.TestConstants.TOSCA_DEFINITION_FILEPATH;
 import static org.openecomp.sdc.vendorsoftwareproduct.impl.orchestration.csar.validation.TestConstants.TOSCA_MANIFEST_FILEPATH;
@@ -74,7 +74,7 @@ public class ValidatorFactoryTest {
     @Test
     public void testGivenNonSOL004MetaDirectoryCompliantMetaFile_thenONAPCSARValidatorIsReturned() throws IOException{
         metaFile = metaFile +
-                TOSCA_META_ENTRY_DEFINITIONS + SEPARATOR_MF_ATTRIBUTE + TOSCA_DEFINITION_FILEPATH;
+                TOSCA_META_ENTRY_DEFINITIONS + ATTRIBUTE_VALUE_SEPARATOR.getToken() + TOSCA_DEFINITION_FILEPATH;
         handler.addFile(TOSCA_META_PATH_FILE_NAME, metaFile.getBytes(StandardCharsets.UTF_8));
 
         assertEquals(ONAPCsarValidator.class, ValidatorFactory.getValidator(handler).getClass());
@@ -84,9 +84,9 @@ public class ValidatorFactoryTest {
     public void testGivenSOL004MetaDirectoryCompliantMetafile_thenONAPCsarValidatorIsReturned() throws IOException{
 
         metaFile = metaFile +
-                TOSCA_META_ENTRY_DEFINITIONS + SEPARATOR_MF_ATTRIBUTE + TOSCA_DEFINITION_FILEPATH + "\n"
-                + TOSCA_META_ETSI_ENTRY_MANIFEST + SEPARATOR_MF_ATTRIBUTE + TOSCA_MANIFEST_FILEPATH + "\n"
-                + TOSCA_META_ETSI_ENTRY_CHANGE_LOG + SEPARATOR_MF_ATTRIBUTE + TOSCA_CHANGELOG_FILEPATH + "\n";
+                TOSCA_META_ENTRY_DEFINITIONS + ATTRIBUTE_VALUE_SEPARATOR.getToken() + TOSCA_DEFINITION_FILEPATH + "\n"
+                + TOSCA_META_ETSI_ENTRY_MANIFEST + ATTRIBUTE_VALUE_SEPARATOR.getToken() + TOSCA_MANIFEST_FILEPATH + "\n"
+                + TOSCA_META_ETSI_ENTRY_CHANGE_LOG + ATTRIBUTE_VALUE_SEPARATOR.getToken() + TOSCA_CHANGELOG_FILEPATH + "\n";
         handler.addFile(TOSCA_META_PATH_FILE_NAME, metaFile.getBytes(StandardCharsets.UTF_8));
 
        assertEquals(SOL004MetaDirectoryValidator.class, ValidatorFactory.getValidator(handler).getClass());
index 77e519c..1228098 100644 (file)
@@ -138,8 +138,9 @@ public class UploadCSARFileTest {
           candidateManager.upload(vspDetails, onboardPackageInfo);
       assertEquals(1, response.getErrors().size());
       assertEquals(response.getErrors().values().iterator().next().get(0).getMessage(),
-          "Manifest " +
-              "contains invalid line : aaa: vCSCF");
+          Messages.MANIFEST_ERROR_WITH_LINE
+              .formatMessage(Messages.MANIFEST_START_METADATA.getErrorMessage(), 1, "aaa: vCSCF")
+      );
 
     }
   }
index 7d2f8b2..2e30126 100644 (file)
@@ -27,16 +27,30 @@ public enum Messages {
   CSAR_FILE_NOT_FOUND("Each CSAR file must contain %s file."),
   CSAR_DIRECTORIES_NOT_ALLOWED("Directory : %s , is not allowed."),
   CSAR_FILES_NOT_ALLOWED("File : %s , are not allowed."),
-  MANIFEST_INVALID_LINE("Manifest contains invalid line : %s"),
+  MANIFEST_INVALID_LINE("Manifest contains invalid line: %s: %s"),
+  MANIFEST_START_METADATA("Manifest must starts with 'metadata:'"),
   MANIFEST_NO_METADATA("Manifest must contain metadata"),
   MANIFEST_NO_SOURCES("Manifest must contain Source"),
   MANIFEST_METADATA_MISSING_ENTRY("Manifest metadata missing entry %s"),
   MANIFEST_INVALID_NAME("Manifest file %s and TOSCA definitions file %s must have the same name"),
   MANIFEST_INVALID_EXT("Manifest file must have extension \".mf\" "),
   MANIFEST_METADATA_INVALID_ENTRY("Manifest metadata should only have pnf or vnf entries"),
+  MANIFEST_METADATA_INVALID_ENTRY1("Invalid Manifest metadata entry: '%s'."),
+  MANIFEST_METADATA_DUPLICATED_ENTRY("Duplicated Manifest metadata entry: '%s'."),
+  MANIFEST_METADATA_UNEXPECTED_ENTRY_TYPE("Manifest metadata should have either pnf or vnf entries, not both together"),
   MANIFEST_INVALID_PNF_METADATA("%s TOSCA.meta file is applicable for VF only"),
-  MANIFEST_METADATA_DOES_NOT_MATCH_LIMIT("Manifest metadata must only have the required number [%s] of values"),
-  MANIFEST_EMPTY("Manifest must contain data"),
+  MANIFEST_INVALID_NON_MANO_KEY("Invalid non mano key '%s'"),
+  MANIFEST_EMPTY_NON_MANO_KEY("Expecting a 'Source' entry for the non mano key '%s'"),
+  MANIFEST_EMPTY_NON_MANO_SOURCE("Empty non mano source"),
+  MANIFEST_EXPECTED_HASH_ENTRY("Expected Hash entry"),
+  MANIFEST_EXPECTED_HASH_VALUE("Expected Hash entry value"),
+  MANIFEST_EXPECTED_SOURCE_PATH("Expected Source entry path"),
+  MANIFEST_EXPECTED_ALGORITHM_VALUE("Expected Algorithm entry value"),
+  MANIFEST_EXPECTED_ALGORITHM_BEFORE_HASH("Expected 'Algorithm' entry before 'Hash' entry"),
+  MANIFEST_DUPLICATED_CMS_SIGNATURE("Duplicated CMS signature"),
+  MANIFEST_METADATA_DOES_NOT_MATCH_LIMIT("Manifest metadata must only have the required number [%s] of entries"),
+  MANIFEST_EMPTY("The manifest is empty"),
+  MANIFEST_ERROR_WITH_LINE("%s;%nAt line %s: '%s'."),
   MANIFEST_PARSER_INTERNAL("Invalid manifest file"),
   METADATA_PARSER_INTERNAL("Invalid Metadata file"),
   METADATA_MISSING_OPTIONAL_FOLDERS("Missing folder %s in package"),
@@ -211,7 +225,7 @@ public enum Messages {
    * @return
    *  The formatted message.
    */
-  public String formatMessage(final String... params) {
+  public String formatMessage(final Object... params) {
     return String.format(errorMessage, params);
   }
 
index bd5a2cc..e3ed721 100644 (file)
@@ -26,7 +26,7 @@ import org.openecomp.core.validation.ErrorMessageCode;
 public class ErrorMessagesFormatBuilder {
   private static final String MESSAGE_PATTERN = "[%s]: %s";
 
-  public static String getErrorWithParameters(String error, String... params) {
+  public static String getErrorWithParameters(String error, Object... params) {
     return String.format(error, params);
   }
   /**
index 33f5168..9029efc 100644 (file)
             <artifactId>logback-classic</artifactId>
             <version>${logback.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>
index a0c346c..7cc11e5 100644 (file)
@@ -19,10 +19,6 @@ package org.openecomp.sdc.tosca.csar;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
-import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
-import org.openecomp.sdc.common.errors.Messages;
-import org.openecomp.sdc.logging.api.Logger;
-import org.openecomp.sdc.logging.api.LoggerFactory;
 import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
@@ -35,21 +31,27 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import org.apache.commons.collections.MapUtils;
+import org.apache.commons.lang.StringUtils;
+import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
+import org.openecomp.sdc.common.errors.Messages;
+import org.openecomp.sdc.logging.api.Logger;
+import org.openecomp.sdc.logging.api.LoggerFactory;
 
-import static org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder.getErrorWithParameters;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.MANIFEST_PNF_METADATA;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.METADATA_MF_ATTRIBUTE;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.SEPARATOR_MF_ATTRIBUTE;
-
- abstract class AbstractOnboardingManifest implements Manifest{
+abstract class AbstractOnboardingManifest implements Manifest {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractOnboardingManifest.class);
-    private static final int MAX_ALLOWED_MANIFEST_META_ENTRIES = 4;
+    protected static final Logger LOGGER = LoggerFactory.getLogger(AbstractOnboardingManifest.class);
+    protected static final int MAX_ALLOWED_MANIFEST_META_ENTRIES = 4;
     protected Map<String, String> metadata;
     protected List<String> sources;
-    protected List<String> errors;
     protected Map<String, List<String>> nonManoSources;
-    protected ResourceTypeEnum type;
+    protected Map<String, AlgorithmDigest> sourceAndChecksumMap = new HashMap<>();
+    protected String cmsSignature;
+    protected List<String> errors;
+    protected boolean continueToProcess;
+    protected String currentLine;
+    protected Iterator<String> linesIterator;
+    protected int currentLineNumber;
 
     protected AbstractOnboardingManifest() {
         errors = new ArrayList<>();
@@ -59,122 +61,327 @@ import static org.openecomp.sdc.tosca.csar.CSARConstants.SEPARATOR_MF_ATTRIBUTE;
     }
 
     @Override
-    public Optional<ResourceTypeEnum> getType(){
-        if(errors.isEmpty() && !metadata.isEmpty() && metadata.size() == MAX_ALLOWED_MANIFEST_META_ENTRIES) {
-            for (String key : metadata.keySet()) {
-                if (MANIFEST_PNF_METADATA.stream().anyMatch(key::equals)) {
-                    return Optional.of(ResourceTypeEnum.PNF);
-                }
-                return Optional.of(ResourceTypeEnum.VF);
-            }
+    public Optional<ResourceTypeEnum> getType() {
+        if (!isValid()) {
+            return Optional.empty();
         }
-        return Optional.empty();
+        final String firstKey = metadata.keySet().iterator().next();
+        final ManifestTokenType manifestTokenType = ManifestTokenType.parse(firstKey).orElse(null);
+        if (manifestTokenType == null) {
+            return Optional.empty();
+        }
+        if (manifestTokenType.isMetadataPnfEntry()) {
+            return Optional.of(ResourceTypeEnum.PNF);
+        }
+        return Optional.of(ResourceTypeEnum.VF);
     }
 
     @Override
-    public void parse(InputStream is) {
+    public void parse(final InputStream manifestAsStream) {
         try {
-            ImmutableList<String> lines = readAllLines(is);
+            final ImmutableList<String> lines = readAllLines(manifestAsStream);
+            continueToProcess = true;
+            currentLineNumber = 0;
             processManifest(lines);
-        } catch (IOException e){
-            LOGGER.error(e.getMessage(),e);
+        } catch (IOException e) {
+            LOGGER.error(e.getMessage(), e);
             errors.add(Messages.MANIFEST_PARSER_INTERNAL.getErrorMessage());
         }
     }
 
-    protected void processManifest(ImmutableList<String> lines) {
-        if (isEmptyManifest(lines)){
+    /**
+     * Process the manifest lines, reporting an error when detected.
+     *
+     * @param lines the manifest lines
+     */
+    protected void processManifest(final ImmutableList<String> lines) {
+        if (isEmptyManifest(lines)) {
             return;
         }
-        Iterator<String> iterator = lines.iterator();
-        //SOL004 #4.3.2: The manifest file shall start with the package metadata
-        String line = iterator.next();
-        if (!isMetadata(line)) {
+        linesIterator = lines.iterator();
+        readNextNonEmptyLine();
+        if (!getCurrentLine().isPresent()) {
+            errors.add(Messages.MANIFEST_EMPTY.getErrorMessage());
             return;
         }
-        //handle metadata
-        processMetadata(iterator);
-        if (errors.isEmpty() && metadata.isEmpty()) {
-                errors.add(Messages.MANIFEST_NO_METADATA.getErrorMessage());
-        }
-    }
-
-    protected abstract void processMetadata(Iterator<String> iterator);
-
-     protected boolean isEmptyLine(Iterator<String> iterator, String line) {
-         if(line.isEmpty()){
-             processMetadata(iterator);
-             return true;
-         }
-         return false;
-     }
-
-     protected boolean isInvalidLine(String line, String[] metaSplit) {
-         if (metaSplit.length < 2){
-             reportError(line);
-             return true;
-         }
-         return false;
-     }
-
-     protected boolean isMetadata(String line) {
-         if(line.trim().equals(METADATA_MF_ATTRIBUTE + SEPARATOR_MF_ATTRIBUTE)){
-             return true;
-         }
-         reportError(line);
-         return false;
-     }
-
-     protected boolean isEmptyManifest(ImmutableList<String> lines) {
-         if(lines == null || lines.isEmpty()){
-             errors.add(Messages.MANIFEST_EMPTY.getErrorMessage());
-             return true;
-         }
-         return false;
-     }
-
-    protected void reportError(String line) {
-        errors.add(getErrorWithParameters(Messages.MANIFEST_INVALID_LINE.getErrorMessage(), line));
-    }
-
-    protected ImmutableList<String> readAllLines(InputStream is) throws IOException {
-        if(is == null){
-            throw new IOException("Input Stream cannot be null!");
-        }
-        ImmutableList.Builder<String> builder = ImmutableList.<String> builder();
-        try (BufferedReader bufferedReader = new BufferedReader(
-                new InputStreamReader(is, StandardCharsets.UTF_8.newDecoder()))) {
+
+        processMetadata();
+        processBody();
+    }
+
+    /**
+     * Process the metadata part of the Manifest file.
+     */
+    protected abstract void processMetadata();
+
+    /**
+     * Process the other parts from manifest different than metadata.
+     */
+    protected abstract void processBody();
+
+    /**
+     * Read the manifest as a list of lines.
+     *
+     * @param manifestAsStream The manifest file input stream
+     * @return The manifest as a list of string
+     * @throws IOException when the input stream is null or a read problem happened.
+     */
+    protected ImmutableList<String> readAllLines(final InputStream manifestAsStream) throws IOException {
+        if (manifestAsStream == null) {
+            throw new IOException("Manifest Input Stream cannot be null.");
+        }
+        final ImmutableList.Builder<String> builder = ImmutableList.builder();
+        try (final BufferedReader bufferedReader = new BufferedReader(
+            new InputStreamReader(manifestAsStream, StandardCharsets.UTF_8.newDecoder()))) {
             bufferedReader.lines().forEach(builder::add);
         }
         return builder.build();
     }
 
+    /**
+     * Checks if the line is a {@link ManifestTokenType#METADATA} entry.
+     *
+     * @param line The line to check
+     * @return {@code true} if the line is a 'metadata' entry, {@code false} otherwise.
+     */
+    protected boolean isMetadata(final String line) {
+        return line.trim()
+            .equals(ManifestTokenType.METADATA.getToken() + ManifestTokenType.ATTRIBUTE_VALUE_SEPARATOR.getToken());
+    }
+
+    /**
+     * Checks if the the entry is a valid metadata entry.
+     *
+     * @param metadataEntry the entry to be evaluated
+     * @return {@code true} if the entry is a valid metadata entry, {@code false} otherwise.
+     */
+    protected boolean isMetadataEntry(final String metadataEntry) {
+        final Optional<ManifestTokenType> manifestTokenType = ManifestTokenType.parse(metadataEntry);
+        return manifestTokenType.map(ManifestTokenType::isMetadataEntry).orElse(false);
+    }
+
+    /**
+     * Checks if the manifest is empty
+     *
+     * @param lines the manifest parsed as a string lines list
+     * @return {@code true} if the manifest is empty, {@code false} otherwise.
+     */
+    protected boolean isEmptyManifest(final ImmutableList<String> lines) {
+        if (lines == null || lines.isEmpty()) {
+            errors.add(Messages.MANIFEST_EMPTY.getErrorMessage());
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Reports a manifest invalid line error occurred in the current line.
+     */
+    protected void reportInvalidLine() {
+        reportInvalidLine(currentLineNumber, getCurrentLine().orElse(""));
+    }
+
+    /**
+     * Reports a manifest invalid line error.
+     *
+     * @param lineNumber the line number
+     * @param line the line
+     */
+    protected void reportInvalidLine(final int lineNumber, final String line) {
+        errors.add(Messages.MANIFEST_INVALID_LINE.formatMessage(lineNumber, line));
+    }
+
+    /**
+     * Reports a manifest error occurred in the current line.
+     *
+     * @param message The error message
+     * @param params The message params
+     */
+    protected void reportError(final Messages message, final Object... params) {
+        reportError(currentLineNumber, getCurrentLine().orElse(""), message, params);
+    }
+
+    /**
+     * Reports a manifest error occurred in the specified line.
+     *
+     * @param lineNumber The line number
+     * @param line The line
+     * @param message The error message
+     * @param params The message params
+     */
+    protected void reportError(final int lineNumber, final String line, final Messages message,
+                               final Object... params) {
+        errors.add(Messages.MANIFEST_ERROR_WITH_LINE.formatMessage(message.formatMessage(params), lineNumber, line));
+    }
+
+    /**
+     * Checks if the manifest is valid.
+     *
+     * @return {@code true} if the manifest is valid, {@code false} otherwise.
+     */
+    public boolean isValid() {
+        return errors.isEmpty();
+    }
+
+    /**
+     * Reads the next non empty line in the manifest. Updates the current line and line number.
+     *
+     * @return the next non empty line. If there is no more lines, an empty value.
+     */
+    protected Optional<String> readNextNonEmptyLine() {
+        while (linesIterator.hasNext()) {
+            final String line = linesIterator.next().trim();
+            currentLineNumber++;
+            if (!line.isEmpty()) {
+                currentLine = line;
+                return getCurrentLine();
+            }
+            currentLine = null;
+        }
+
+        if (getCurrentLine().isPresent()) {
+            currentLineNumber++;
+            currentLine = null;
+        }
+
+        return getCurrentLine();
+    }
+
+    /**
+     * Gets the current line.
+     *
+     * @return the current line.
+     */
+    protected Optional<String> getCurrentLine() {
+        return Optional.ofNullable(currentLine);
+    }
+
+    /**
+     * Reads the current line entry name. The entry name and value must be separated by {@link
+     * ManifestTokenType#ATTRIBUTE_VALUE_SEPARATOR}.
+     *
+     * @return the entry value
+     */
+    protected Optional<String> readCurrentEntryName() {
+        final Optional<String> line = getCurrentLine();
+        if (line.isPresent()) {
+            return readEntryName(line.get());
+        }
+
+        return Optional.empty();
+    }
+
+    /**
+     * Read a entry name. The entry name and value must be separated by {@link ManifestTokenType#ATTRIBUTE_VALUE_SEPARATOR}.
+     *
+     * @param line the entry line
+     * @return returns the entry name
+     */
+    protected Optional<String> readEntryName(final String line) {
+        if (StringUtils.isEmpty(line)) {
+            return Optional.empty();
+        }
+        if (!line.contains(ManifestTokenType.ATTRIBUTE_VALUE_SEPARATOR.getToken())) {
+            return Optional.empty();
+        }
+        final String attribute = line.substring(0, line.indexOf(ManifestTokenType.ATTRIBUTE_VALUE_SEPARATOR.getToken())).trim();
+        if (StringUtils.isEmpty(attribute)) {
+            return Optional.empty();
+        }
+
+        return Optional.of(attribute);
+    }
+
+    /**
+     * Reads the current line entry value. The entry name and value must be separated by {@link
+     * ManifestTokenType#ATTRIBUTE_VALUE_SEPARATOR}.
+     *
+     * @return the entry value
+     */
+    protected Optional<String> readCurrentEntryValue() {
+        final Optional<String> line = getCurrentLine();
+        if (line.isPresent()) {
+            return readEntryValue(line.get());
+        }
+
+        return Optional.empty();
+    }
+
+    /**
+     * Reads a entry value. The entry name and value must be separated by {@link ManifestTokenType#ATTRIBUTE_VALUE_SEPARATOR}.
+     *
+     * @param line the entry line
+     * @return the entry value
+     */
+    protected Optional<String> readEntryValue(final String line) {
+        if (StringUtils.isEmpty(line)) {
+            return Optional.empty();
+        }
+        if (!line.contains(ManifestTokenType.ATTRIBUTE_VALUE_SEPARATOR.getToken())) {
+            return Optional.empty();
+        }
+        final String value = line.substring(line.indexOf(ManifestTokenType.ATTRIBUTE_VALUE_SEPARATOR.getToken()) + 1).trim();
+        if (StringUtils.isEmpty(value)) {
+            return Optional.empty();
+        }
+
+        return Optional.of(value);
+    }
+
+    /**
+     * Adds a entry to the metadata map. Only accepts new entries. If the entry is duplicated a manifest error is
+     * reported.
+     *
+     * @param entry the metadata entry
+     * @param value the entry value
+     * @return {@code true} if the entry was added, {@code false} otherwise.
+     */
+    protected boolean addToMetadata(final String entry, final String value) {
+        if (metadata.containsKey(entry)) {
+            reportError(Messages.MANIFEST_METADATA_DUPLICATED_ENTRY, entry);
+            return false;
+        }
+
+        metadata.put(entry, value);
+        return true;
+    }
+
+    public List<String> getErrors() {
+        return ImmutableList.copyOf(errors);
+    }
+
     public Map<String, String> getMetadata() {
-        if (!isValid()){
+        if (!isValid()) {
             return Collections.emptyMap();
         }
         return ImmutableMap.copyOf(metadata);
     }
 
     public List<String> getSources() {
-        if (!isValid()){
+        if (!isValid()) {
             return Collections.emptyList();
         }
         return ImmutableList.copyOf(sources);
     }
 
-    public List<String> getErrors() {
-        return  ImmutableList.copyOf(errors);
+    public Map<String, List<String>> getNonManoSources() {
+        if (!isValid()) {
+            return Collections.emptyMap();
+        }
+        return ImmutableMap.copyOf(nonManoSources);
     }
 
-    public boolean isValid() {
-        return errors.isEmpty();
+    @Override
+    public Optional<String> getCmsSignature() {
+        return Optional.ofNullable(cmsSignature);
     }
 
-    public Map<String, List<String>> getNonManoSources() {
-        if (!isValid()){
-            return Collections.emptyMap();
+    @Override
+    public Optional<Map<String, AlgorithmDigest>> getSourceAndChecksumMap() {
+        if (MapUtils.isEmpty(sourceAndChecksumMap)) {
+            return Optional.empty();
         }
-        return ImmutableMap.copyOf(nonManoSources);
+
+        return Optional.of(ImmutableMap.copyOf(sourceAndChecksumMap));
     }
 }
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/AlgorithmDigest.java b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/AlgorithmDigest.java
new file mode 100644 (file)
index 0000000..8ce0fb6
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * ============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.tosca.csar;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * Represents a manifest Hash algorithm and Digest
+ */
+@Getter
+@AllArgsConstructor
+public class AlgorithmDigest {
+    private final String hashAlgorithm;
+    private final String digest;
+}
index 7a42758..1de91f9 100644 (file)
 package org.openecomp.sdc.tosca.csar;
 
 import static com.google.common.collect.ImmutableSet.of;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.PNFD_ARCHIVE_VERSION;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.PNFD_NAME;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.PNFD_PROVIDER;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.PNFD_RELEASE_DATE_TIME;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNF_PACKAGE_VERSION;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNF_PRODUCT_NAME;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNF_PROVIDER_ID;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.VNF_RELEASE_DATE_TIME;
 
 import com.google.common.collect.ImmutableSet;
 
@@ -34,37 +42,21 @@ public class CSARConstants {
     public static final String TOSCA_META_CSAR_VERSION_ENTRY = "CSAR-Version";
     public static final String TOSCA_META_CREATED_BY_ENTRY = "Created-By";
     public static final String TOSCA_META_ENTRY_DEFINITIONS ="Entry-Definitions";
-    public static final String TOSCA_META_ETSI_ENTRY_MANIFEST ="ETSI-Entry-Manifest";
-    public static final String TOSCA_META_ETSI_ENTRY_CHANGE_LOG ="ETSI-Entry-Change-Log";
+    public static final String TOSCA_META_ETSI_ENTRY_MANIFEST = "ETSI-Entry-Manifest";
+    public static final String TOSCA_META_ETSI_ENTRY_CHANGE_LOG = "ETSI-Entry-Change-Log";
     public static final String TOSCA_META_ETSI_ENTRY_TESTS = "ETSI-Entry-Tests";
     public static final String TOSCA_META_ETSI_ENTRY_LICENSES = "ETSI-Entry-Licenses";
     public static final String TOSCA_META_ETSI_ENTRY_CERTIFICATE = "ETSI-Entry-Certificate";
     public static final ImmutableSet<String> ELIGIBLE_FILES =
             of(MAIN_SERVICE_TEMPLATE_MF_FILE_NAME,MAIN_SERVICE_TEMPLATE_YAML_FILE_NAME);
 
-    public static final String PNFD_PROVIDER = "pnfd_provider";
-    public static final String PNFD_NAME = "pnfd_name";
-    public static final String PNFD_RELEASE_DATE_TIME = "pnfd_release_date_time";
-    public static final String PNFD_ARCHIVE_VERSION = "pnfd_archive_version";
     public static final ImmutableSet<String> MANIFEST_PNF_METADATA =
-        of(PNFD_PROVIDER, PNFD_NAME, PNFD_RELEASE_DATE_TIME, PNFD_ARCHIVE_VERSION);
-
-    public static final String VNF_PROVIDER_ID = "vnf_provider_id";
-    public static final String VNF_PRODUCT_NAME = "vnf_product_name";
-    public static final String VNF_RELEASE_DATE_TIME = "vnf_release_date_time";
-    public static final String VNF_PACKAGE_VERSION = "vnf_package_version";
+        of(PNFD_PROVIDER.getToken(), PNFD_NAME.getToken(), PNFD_RELEASE_DATE_TIME.getToken(),
+            PNFD_ARCHIVE_VERSION.getToken());
     public static final ImmutableSet<String> MANIFEST_VNF_METADATA =
-            of(VNF_PROVIDER_ID, VNF_PRODUCT_NAME, VNF_RELEASE_DATE_TIME, VNF_PACKAGE_VERSION);
-
+            of(VNF_PROVIDER_ID.getToken(), VNF_PRODUCT_NAME.getToken(), VNF_RELEASE_DATE_TIME.getToken(),
+                VNF_PACKAGE_VERSION.getToken());
     public static final int MANIFEST_METADATA_LIMIT = 4;
-    public static final String METADATA_MF_ATTRIBUTE = "metadata";
-    public static final String SOURCE_MF_ATTRIBUTE = "Source";
-    public static final String ALGORITHM_MF_ATTRIBUTE = "Algorithm";
-    public static final String HASH_MF_ATTRIBUTE = "Hash";
-    public static final String CMS_BEGIN = "----BEGIN CMS-----";
-    public static final String CMD_END = "----END CMS-----";
-    public static final String SEPARATOR_MF_ATTRIBUTE = ":";
-    public static final String NON_MANO_MF_ATTRIBUTE = "non_mano_artifact_sets";
     public static final String TOSCA_META_ORIG_PATH_FILE_NAME = "TOSCA-Metadata/TOSCA.meta.original";
 
     public static final String TOSCA_META_FILE_VERSION = "1.0";
index c11f4a3..c0ccbbc 100644 (file)
 
 package org.openecomp.sdc.tosca.csar;
 
-import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
 import java.io.InputStream;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
 
 public interface Manifest {
 
@@ -70,4 +70,18 @@ public interface Manifest {
      * @return enum for type values
      */
     Optional<ResourceTypeEnum> getType();
+
+    /**
+     * Gets the CMS manifest signature if present in manifest
+     * @return
+     *  the CMS manifest signature.
+     */
+    Optional<String> getCmsSignature();
+
+    /**
+     * Gets the Map of source path and it correspondent checksum.
+     * @return
+     *  The source and checksum map.
+     */
+    Optional<Map<String, AlgorithmDigest>> getSourceAndChecksumMap();
 }
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/ManifestTokenType.java b/openecomp-be/lib/openecomp-tosca-lib/src/main/java/org/openecomp/sdc/tosca/csar/ManifestTokenType.java
new file mode 100644 (file)
index 0000000..68ad91d
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * ============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.tosca.csar;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+public enum ManifestTokenType {
+    ALGORITHM("Algorithm"),
+    ATTRIBUTE_VALUE_SEPARATOR(":"),
+    CMS_BEGIN("-----BEGIN CMS-----"),
+    CMS_END("-----END CMS-----"),
+    HASH("Hash"),
+    METADATA("metadata"),
+    NON_MANO_ARTIFACT_SETS("non_mano_artifact_sets"),
+    SOURCE("Source"),
+    VNF_PRODUCT_NAME("vnf_product_name"),
+    VNF_PROVIDER_ID("vnf_provider_id"),
+    VNF_PACKAGE_VERSION("vnf_package_version"),
+    VNF_RELEASE_DATE_TIME("vnf_release_date_time"),
+    PNFD_NAME("pnfd_name"),
+    PNFD_PROVIDER("pnfd_provider"),
+    PNFD_ARCHIVE_VERSION("pnfd_archive_version"),
+    PNFD_RELEASE_DATE_TIME("pnfd_release_date_time");
+
+    private final String token;
+
+    ManifestTokenType(final String token) {
+        this.token = token;
+    }
+
+    public String getToken() {
+        return token;
+    }
+
+    public static Optional<ManifestTokenType> parse(final String token) {
+        return Arrays.stream(values()).filter(it -> it.getToken() != null && it.getToken().equals(token)).findFirst();
+    }
+
+    public boolean isMetadataEntry() {
+        return isMetadataVnfEntry() || isMetadataPnfEntry();
+    }
+
+    public boolean isMetadataVnfEntry() {
+        switch (this) {
+            case VNF_PRODUCT_NAME:
+            case VNF_PROVIDER_ID:
+            case VNF_PACKAGE_VERSION:
+            case VNF_RELEASE_DATE_TIME:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public boolean isMetadataPnfEntry() {
+        switch (this) {
+            case PNFD_NAME:
+            case PNFD_PROVIDER:
+            case PNFD_ARCHIVE_VERSION:
+            case PNFD_RELEASE_DATE_TIME:
+                return true;
+            default:
+                return false;
+        }
+    }
+}
index 2c4cc3a..02ee12d 100644 (file)
 package org.openecomp.sdc.tosca.csar;
 
 import com.google.common.collect.ImmutableList;
+import java.util.Optional;
 import org.openecomp.sdc.common.errors.Messages;
-import java.util.Iterator;
 
-import static org.openecomp.sdc.tosca.csar.CSARConstants.SEPARATOR_MF_ATTRIBUTE;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.SOURCE_MF_ATTRIBUTE;
-
-public class ONAPManifestOnboarding extends AbstractOnboardingManifest implements Manifest {
+public class ONAPManifestOnboarding extends AbstractOnboardingManifest {
 
     @Override
     protected void processManifest(ImmutableList<String> lines) {
         super.processManifest(lines);
         if (errors.isEmpty() && sources.isEmpty()) {
-                errors.add(Messages.MANIFEST_NO_SOURCES.getErrorMessage());
+            errors.add(Messages.MANIFEST_NO_SOURCES.getErrorMessage());
         }
     }
 
     @Override
-    protected void processMetadata(Iterator<String> iterator) {
-        if(!iterator.hasNext()){
-            return;
-        }
-        String line = iterator.next();
-        if(isEmptyLine(iterator, line)) {
-            return;
-        }
-        String[] metaSplit = line.split(SEPARATOR_MF_ATTRIBUTE);
-        if (isInvalidLine(line, metaSplit)) {
+    protected void processMetadata() {
+        Optional<String> currentLine = getCurrentLine();
+        if (!currentLine.isPresent() || !isMetadata(currentLine.get())) {
+            reportError(Messages.MANIFEST_START_METADATA);
+            continueToProcess = false;
             return;
         }
-        if (!metaSplit[0].equals(SOURCE_MF_ATTRIBUTE)){
-            String value = line.substring((metaSplit[0] + SEPARATOR_MF_ATTRIBUTE).length()).trim();
-            metadata.put(metaSplit[0].trim(),value.trim());
-            processMetadata(iterator);
-        }else if(metaSplit[0].startsWith(SOURCE_MF_ATTRIBUTE)){
-            String value = line.substring((metaSplit[0] + SEPARATOR_MF_ATTRIBUTE).length()).trim();
-            sources.add(value);
-            processMetadata(iterator);
+        currentLine = readNextNonEmptyLine();
+
+        while (currentLine.isPresent() && continueToProcess) {
+            final String line = currentLine.get();
+            final String entry = readEntryName(line).orElse(null);
+            if (entry == null) {
+                reportInvalidLine();
+            }
+            final String value = readEntryValue(line).orElse(null);
+            if (value == null) {
+                reportInvalidLine();
+            }
+
+            final ManifestTokenType tokenType = ManifestTokenType.parse(entry).orElse(null);
+            if (tokenType == ManifestTokenType.SOURCE) {
+                sources.add(value);
+            } else {
+                addToMetadata(entry, value);
+                continueToProcess = isValid();
+            }
+            currentLine = readNextNonEmptyLine();
         }
     }
 
+    @Override
+    protected void processBody() {
+        //no implementation
+    }
+
 }
index 8d603cc..3fc55ad 100644 (file)
@@ -36,10 +36,10 @@ import java.util.List;
 import java.util.Map;
 
 import static org.openecomp.core.validation.errors.ErrorMessagesFormatBuilder.getErrorWithParameters;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.SEPARATOR_MF_ATTRIBUTE;
 import static org.openecomp.sdc.tosca.csar.CSARConstants.TOSCA_META_ENTRY_DEFINITIONS;
+import static org.openecomp.sdc.tosca.csar.ManifestTokenType.ATTRIBUTE_VALUE_SEPARATOR;
 
-public class OnboardingToscaMetadata implements ToscaMetadata{
+public class OnboardingToscaMetadata implements ToscaMetadata {
 
   private Map<String, String> metaEntries;
   private List<ErrorMessage> errors;
@@ -66,7 +66,7 @@ public class OnboardingToscaMetadata implements ToscaMetadata{
       if (line.isEmpty()) {
         return meta;
       }
-      String[] entry = line.split(SEPARATOR_MF_ATTRIBUTE);
+      String[] entry = line.split(ATTRIBUTE_VALUE_SEPARATOR.getToken());
       //No empty keys allowed, no empty values allowed
       if (entry.length < 2 || entry[0].isEmpty()) {
         meta.errors.add(new ErrorMessage(ErrorLevel.ERROR, getErrorWithParameters(
index b5b3d9c..bb0b07a 100644 (file)
 package org.openecomp.sdc.tosca.csar;
 
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
+import java.util.Map.Entry;
+import java.util.Optional;
+import org.apache.commons.lang.StringUtils;
+import org.openecomp.sdc.common.errors.Messages;
 
-import static org.openecomp.sdc.tosca.csar.CSARConstants.ALGORITHM_MF_ATTRIBUTE;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.CMD_END;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.CMS_BEGIN;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.HASH_MF_ATTRIBUTE;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.NON_MANO_MF_ATTRIBUTE;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.SEPARATOR_MF_ATTRIBUTE;
-import static org.openecomp.sdc.tosca.csar.CSARConstants.SOURCE_MF_ATTRIBUTE;
-
+/**
+ * Processes a SOL004 Manifest.
+ */
 public class SOL004ManifestOnboarding extends AbstractOnboardingManifest {
 
     @Override
-    protected void processMetadata(Iterator<String> iterator) {
-        if(!iterator.hasNext()){
+    protected void processMetadata() {
+        Optional<String> currentLine = getCurrentLine();
+        //SOL004 #4.3.2: The manifest file shall start with the package metadata
+        if (!currentLine.isPresent() || !isMetadata(currentLine.get())) {
+            reportError(Messages.MANIFEST_START_METADATA);
+            continueToProcess = false;
             return;
         }
-        String line = iterator.next();
-        if(isEmptyLine(iterator, line)){
+        while (continueToProcess) {
+            currentLine = readNextNonEmptyLine();
+            if (!currentLine.isPresent()) {
+                continueToProcess = validateMetadata();
+                return;
+            }
+            final String metadataLine = currentLine.get();
+            final String metadataEntry = readEntryName(metadataLine).orElse(null);
+            if (!isMetadataEntry(metadataEntry)) {
+                if (metadata.size() < MAX_ALLOWED_MANIFEST_META_ENTRIES) {
+                    reportError(Messages.MANIFEST_METADATA_INVALID_ENTRY1, metadataLine);
+                    continueToProcess = false;
+                    return;
+                }
+                continueToProcess = validateMetadata();
+                return;
+            }
+            final String metadataValue = readEntryValue(metadataLine).orElse(null);
+            addToMetadata(metadataEntry, metadataValue);
+            continueToProcess = isValid();
+        }
+        readNextNonEmptyLine();
+    }
+
+    @Override
+    protected void processBody() {
+        while (continueToProcess) {
+            final ManifestTokenType manifestTokenType = detectLineEntry().orElse(null);
+            if (manifestTokenType == null) {
+                getCurrentLine().ifPresent(line -> reportInvalidLine());
+                break;
+            }
+
+            switch (manifestTokenType) {
+                case CMS_BEGIN:
+                    readCmsSignature();
+                    break;
+                case NON_MANO_ARTIFACT_SETS:
+                    processNonManoArtifactEntry();
+                    continueToProcess = false;
+                    break;
+                case SOURCE:
+                    processSource();
+                    break;
+                default:
+                    getCurrentLine().ifPresent(line -> reportInvalidLine());
+                    continueToProcess = false;
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Processes the {@link ManifestTokenType#NON_MANO_ARTIFACT_SETS} entry.
+     */
+    private void processNonManoArtifactEntry() {
+        Optional<String> currentLine = readNextNonEmptyLine();
+        while (currentLine.isPresent()) {
+            final ManifestTokenType manifestTokenType = detectLineEntry().orElse(null);
+            if (manifestTokenType != null) {
+                reportError(Messages.MANIFEST_INVALID_NON_MANO_KEY, manifestTokenType.getToken());
+                continueToProcess = false;
+                return;
+            }
+            final String nonManoKey = readCurrentEntryName().orElse(null);
+            if (nonManoKey == null) {
+                reportError(Messages.MANIFEST_INVALID_NON_MANO_KEY, currentLine.get());
+                continueToProcess = false;
+                return;
+            }
+            readNextNonEmptyLine();
+            final List<String> nonManoSourceList = readNonManoSourceList();
+            if (!isValid()) {
+                continueToProcess = false;
+                return;
+            }
+            if (nonManoSourceList.isEmpty()) {
+                reportError(Messages.MANIFEST_EMPTY_NON_MANO_KEY, nonManoKey);
+                continueToProcess = false;
+                return;
+            }
+            if (nonManoSources.get(nonManoKey) == null) {
+                nonManoSources.put(nonManoKey, nonManoSourceList);
+            } else {
+                nonManoSources.get(nonManoKey).addAll(nonManoSourceList);
+            }
+            currentLine = getCurrentLine();
+        }
+    }
+
+    /**
+     * Processes {@link ManifestTokenType#SOURCE} entries in {@link ManifestTokenType#NON_MANO_ARTIFACT_SETS}.
+     *
+     * @return A list of sources paths
+     */
+    private List<String> readNonManoSourceList() {
+        final List<String> nonManoSourceList = new ArrayList<>();
+        while (getCurrentLine().isPresent()) {
+            final ManifestTokenType manifestTokenType = detectLineEntry().orElse(null);
+            if (manifestTokenType != ManifestTokenType.SOURCE) {
+                break;
+            }
+
+            final String value = readCurrentEntryValue().orElse(null);
+            if (!StringUtils.isEmpty(value)) {
+                nonManoSourceList.add(value);
+            } else {
+                reportError(Messages.MANIFEST_EMPTY_NON_MANO_SOURCE);
+                break;
+            }
+
+            readNextNonEmptyLine();
+        }
+        return nonManoSourceList;
+    }
+
+    /**
+     * Reads a manifest CMS signature.
+     */
+    private void readCmsSignature() {
+        if (cmsSignature != null) {
+            reportError(Messages.MANIFEST_DUPLICATED_CMS_SIGNATURE);
+            continueToProcess = false;
             return;
         }
-        String[] metaSplit = line.split(SEPARATOR_MF_ATTRIBUTE);
-        if (isInvalidLine(line, metaSplit)) {
+        Optional<String> currentLine = readNextNonEmptyLine();
+        if(!getCurrentLine().isPresent()) {
             return;
         }
-        if (!metaSplit[0].equals(SOURCE_MF_ATTRIBUTE) && !metaSplit[0].equals(NON_MANO_MF_ATTRIBUTE)){
-            String value = line.substring((metaSplit[0] + SEPARATOR_MF_ATTRIBUTE).length()).trim();
-            metadata.put(metaSplit[0].trim(),value.trim());
-            processMetadata(iterator);
-        } else {
-            processSourcesAndNonManoSources(iterator, line);
+        StringBuilder stringBuilder = new StringBuilder();
+        while (currentLine.isPresent() && detectLineEntry().orElse(null) != ManifestTokenType.CMS_END) {
+            stringBuilder.append(currentLine.get());
+            stringBuilder.append("\n");
+            currentLine = readNextNonEmptyLine();
+        }
+
+        if (currentLine.isPresent()) {
+            cmsSignature = stringBuilder.toString();
+            readNextNonEmptyLine();
         }
     }
 
-    private void processSourcesAndNonManoSources(Iterator<String> iterator, String prevLine) {
-        if(prevLine.isEmpty()){
-            if(iterator.hasNext()){
-                processSourcesAndNonManoSources(iterator, iterator.next());
+    /**
+     * Detects the current line manifest token.
+     *
+     * @return the current line manifest token.
+     */
+    private Optional<ManifestTokenType> detectLineEntry() {
+        final Optional<String> currentLine = getCurrentLine();
+        if (currentLine.isPresent()) {
+            final String line = currentLine.get();
+            final String entry = readEntryName(line).orElse(null);
+            if (entry == null) {
+                return ManifestTokenType.parse(line);
+            } else {
+                return ManifestTokenType.parse(entry);
             }
-        } else if(prevLine.startsWith(SOURCE_MF_ATTRIBUTE+ SEPARATOR_MF_ATTRIBUTE)){
-            processSource(iterator, prevLine);
-        }
-        else if(prevLine.startsWith(ALGORITHM_MF_ATTRIBUTE + SEPARATOR_MF_ATTRIBUTE) ||
-                prevLine.startsWith(HASH_MF_ATTRIBUTE + SEPARATOR_MF_ATTRIBUTE)){
-            processSourcesAndNonManoSources(iterator, iterator.next());
-        }else if(prevLine.startsWith(CMS_BEGIN)){
-            String line = iterator.next();
-            while(iterator.hasNext() && !line.contains(CMD_END)){
-               line = iterator.next();
+        }
+        return Optional.empty();
+    }
+
+    /**
+     * Validates the manifest metadata content, reporting errors found.
+     *
+     * @return {@code true} if the metadata content is valid, {@code false} otherwise.
+     */
+    private boolean validateMetadata() {
+        if (metadata.isEmpty()) {
+            reportError(Messages.MANIFEST_NO_METADATA);
+            return false;
+        }
+
+        final Entry<String, String> firstManifestEntry = metadata.entrySet().iterator().next();
+        final ManifestTokenType firstManifestEntryTokenType =
+            ManifestTokenType.parse(firstManifestEntry.getKey()).orElse(null);
+        if (firstManifestEntryTokenType == null) {
+            reportError(Messages.MANIFEST_METADATA_INVALID_ENTRY1, firstManifestEntry.getKey());
+            return false;
+        }
+        for (final Entry<String, String> manifestEntry : metadata.entrySet()) {
+            final ManifestTokenType manifestEntryTokenType = ManifestTokenType.parse(manifestEntry.getKey())
+                .orElse(null);
+            if (manifestEntryTokenType == null) {
+                reportError(Messages.MANIFEST_METADATA_INVALID_ENTRY1, manifestEntry.getKey());
+                return false;
+            }
+            if ((firstManifestEntryTokenType.isMetadataVnfEntry() && !manifestEntryTokenType.isMetadataVnfEntry())
+                || (firstManifestEntryTokenType.isMetadataPnfEntry() && !manifestEntryTokenType.isMetadataPnfEntry())) {
+                reportError(Messages.MANIFEST_METADATA_UNEXPECTED_ENTRY_TYPE);
+                return false;
             }
-            processSourcesAndNonManoSources(iterator, iterator.next());
         }
-        else if(prevLine.startsWith(NON_MANO_MF_ATTRIBUTE+ SEPARATOR_MF_ATTRIBUTE)){
-            //non mano should be the last bit in manifest file,
-            // all sources after non mano will be placed to the last non mano
-            // key, if any other structure met error reported
-            processNonManoInputs(iterator, iterator.next());
-        }else{
-            reportError(prevLine);
+
+        if (metadata.entrySet().size() != MAX_ALLOWED_MANIFEST_META_ENTRIES) {
+            reportError(Messages.MANIFEST_METADATA_DOES_NOT_MATCH_LIMIT, MAX_ALLOWED_MANIFEST_META_ENTRIES);
+            return false;
         }
+
+        return true;
     }
 
-    private void processSource(Iterator<String> iterator, String prevLine) {
-        String value = prevLine.substring((SOURCE_MF_ATTRIBUTE + SEPARATOR_MF_ATTRIBUTE).length()).trim();
-        sources.add(value);
-        if(iterator.hasNext()) {
-            processSourcesAndNonManoSources(iterator, iterator.next());
+    /**
+     * Processes a Manifest {@link ManifestTokenType#SOURCE} entry.
+     */
+    private void processSource() {
+        final Optional<String> currentLine = getCurrentLine();
+        if (!currentLine.isPresent()) {
+            return;
+        }
+        final ManifestTokenType manifestTokenType = detectLineEntry().orElse(null);
+        if (manifestTokenType != ManifestTokenType.SOURCE) {
+            return;
+        }
+
+        final String sourceLine = currentLine.get();
+        final String sourcePath = readEntryValue(sourceLine).orElse(null);
+
+        if (sourcePath == null) {
+            reportError(Messages.MANIFEST_EXPECTED_SOURCE_PATH);
+            return;
         }
+        sources.add(sourcePath);
+        readAlgorithmEntry(sourcePath);
     }
 
-    private void processNonManoInputs(Iterator<String> iterator, String prevLine) {
-        if(prevLine.trim().equals(SOURCE_MF_ATTRIBUTE + SEPARATOR_MF_ATTRIBUTE)){
-            reportError(prevLine);
+    /**
+     * Processes entries  {@link ManifestTokenType#ALGORITHM} and {@link ManifestTokenType#HASH} of a {@link
+     * ManifestTokenType#SOURCE} entry.
+     *
+     * @param sourcePath the source path related to the algorithm entry.
+     */
+    private void readAlgorithmEntry(final String sourcePath) {
+        Optional<String> currentLine = readNextNonEmptyLine();
+        if (!currentLine.isPresent()) {
             return;
         }
-        if(!prevLine.contains(SEPARATOR_MF_ATTRIBUTE)){
-            reportError(prevLine);
+        final ManifestTokenType manifestTokenType = detectLineEntry().orElse(null);
+        if (manifestTokenType == ManifestTokenType.HASH) {
+            reportError(Messages.MANIFEST_EXPECTED_ALGORITHM_BEFORE_HASH);
+            continueToProcess = false;
             return;
         }
-
-        String[] metaSplit = prevLine.trim().split(SEPARATOR_MF_ATTRIBUTE);
-        if (metaSplit.length > 1){
-            reportError(prevLine);
+        if (manifestTokenType != ManifestTokenType.ALGORITHM) {
             return;
         }
-        int index = prevLine.indexOf(':');
-        if(index > 0){
-            prevLine = prevLine.substring(0, index);
+        final String algorithmLine = currentLine.get();
+        final String algorithmType = readEntryValue(algorithmLine).orElse(null);
+        if (algorithmType == null) {
+            reportError(Messages.MANIFEST_EXPECTED_ALGORITHM_VALUE);
+            continueToProcess = false;
+            return;
         }
-        processNonManoSource(iterator, prevLine, new ArrayList<>());
 
-    }
+        currentLine = readNextNonEmptyLine();
+        if (!currentLine.isPresent() || detectLineEntry().orElse(null) != ManifestTokenType.HASH) {
+            reportError(Messages.MANIFEST_EXPECTED_HASH_ENTRY);
+            continueToProcess = false;
+            return;
+        }
 
-    private void processNonManoSource(Iterator<String> iterator, String key, List<String> sources) {
-        if(!iterator.hasNext()){
+        final String hashLine = currentLine.get();
+        final String hash = readEntryValue(hashLine).orElse(null);
+        if (hash == null) {
+            reportError(Messages.MANIFEST_EXPECTED_HASH_VALUE);
+            continueToProcess = false;
             return;
         }
-        String line = iterator.next();
-        if(line.isEmpty()){
-            processNonManoSource(iterator, key, sources);
-        }else if(line.trim().startsWith(SOURCE_MF_ATTRIBUTE + SEPARATOR_MF_ATTRIBUTE)){
-            String value = line.replace(SOURCE_MF_ATTRIBUTE + SEPARATOR_MF_ATTRIBUTE, "").trim();
-            sources.add(value);
-            processNonManoSource(iterator, key, sources);
-        }else {
-            processNonManoInputs(iterator, line);
-        }
-        nonManoSources.put(key.trim(), sources);
+        sourceAndChecksumMap.put(sourcePath, new AlgorithmDigest(algorithmType, hash));
+        readNextNonEmptyLine();
     }
+
 }
\ No newline at end of file
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/java/org/openecomp/sdc/tosca/csar/ManifestParsingTest.java b/openecomp-be/lib/openecomp-tosca-lib/src/test/java/org/openecomp/sdc/tosca/csar/ManifestParsingTest.java
deleted file mode 100644 (file)
index b083cfa..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright Â© 2016-2018 European Support Limited
- *
- * 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.
- */
-
-package org.openecomp.sdc.tosca.csar;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
-import org.openecomp.sdc.common.errors.Messages;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Optional;
-
-import static junit.framework.TestCase.assertTrue;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-
-
-public class ManifestParsingTest {
-
-  private Manifest manifest;
-
-  @Before
-  public void setUp(){
-    manifest = new SOL004ManifestOnboarding();
-  }
-
-  @Test
-  public void testSuccessfulParsing() throws IOException {
-    try (InputStream is = getClass()
-        .getResourceAsStream("/vspmanager.csar/manifest/ValidTosca.mf")) {
-      manifest.parse(is);
-      assertTrue(manifest.isValid());
-      assertEquals(manifest.getMetadata().size(), 4);
-      assertEquals(manifest.getSources().size(), 5);
-      Optional<ResourceTypeEnum> resourceTypeEnum = manifest.getType();
-      if(resourceTypeEnum.isPresent()){
-        assertTrue(resourceTypeEnum.get() == ResourceTypeEnum.VF);
-      }
-    }
-  }
-
-  @Test
-  public void testNoMetadataParsing() throws IOException {
-    try (InputStream is = getClass()
-        .getResourceAsStream("/vspmanager.csar/manifest/InvalidTosca1.mf")) {
-      manifest.parse(is);
-      assertFalse(manifest.isValid());
-      assertTrue(manifest.getErrors().stream().anyMatch(error -> error
-          .contains(Messages.MANIFEST_INVALID_LINE.getErrorMessage().substring(0, 10))));
-    }
-  }
-
-  @Test
-  public void testBrokenMDParsing() throws IOException {
-    try (InputStream is = getClass()
-        .getResourceAsStream("/vspmanager.csar/manifest/InvalidTosca2.mf")) {
-     manifest.parse(is);
-      assertFalse(manifest.isValid());
-      assertTrue(manifest.getErrors().stream().anyMatch(error -> error
-          .contains(Messages.MANIFEST_INVALID_LINE.getErrorMessage().substring(0, 10))));
-    }
-  }
-
-  @Test
-  public void testNoMetaParsing() throws IOException {
-    try (InputStream is = getClass()
-        .getResourceAsStream("/vspmanager.csar/manifest/InvalidTosca4.mf")) {
-      manifest.parse(is);
-      assertFalse(manifest.isValid());
-      assertTrue(manifest.getErrors().stream().anyMatch(error -> error
-          .contains(Messages.MANIFEST_NO_METADATA.getErrorMessage().substring(0, 10))));
-    }
-  }
-
-  @Test
-  public void testSuccessfulNonManoParsing() throws IOException {
-    try (InputStream is = getClass()
-            .getResourceAsStream("/vspmanager.csar/manifest/ValidNonManoTosca.mf")) {
-      manifest.parse(is);
-      assertTrue(manifest.isValid());
-      assertEquals(manifest.getMetadata().size(), 4);
-      assertEquals(manifest.getSources().size(), 5);
-      assertEquals(manifest.getNonManoSources().size(), 2);
-    }
-  }
-
-  @Test
-  public void testFailfulNonManoParsing() throws IOException {
-    try (InputStream is = getClass()
-            .getResourceAsStream("/vspmanager.csar/manifest/InValidNonManoTosca.mf")) {
-      manifest.parse(is);
-      assertFalse(manifest.isValid());
-    }
-  }
-
-  @Test
-  public void testFailfulNonManoParsingWithGarbadge() throws IOException {
-    try (InputStream is = getClass()
-            .getResourceAsStream("/vspmanager.csar/manifest/InvalidTocsaNonManoGarbadgeAtEnd.mf")) {
-      manifest.parse(is);
-      assertFalse(manifest.isValid());
-    }
-  }
-
-  @Test
-  public void testParseManifestWithNoFile() throws IOException {
-    try (InputStream is = getClass()
-            .getResourceAsStream("/vspmanager.csar/manifest/SOME_WRONG_FILE")) {
-      manifest.parse(is);
-      assertFalse(manifest.isValid());
-    }
-  }
-}
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/java/org/openecomp/sdc/tosca/csar/SOL004ManifestOnboardingTest.java b/openecomp-be/lib/openecomp-tosca-lib/src/test/java/org/openecomp/sdc/tosca/csar/SOL004ManifestOnboardingTest.java
new file mode 100644 (file)
index 0000000..7cb1511
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * Copyright Â© 2016-2018 European Support Limited
+ *
+ * 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.
+ */
+
+package org.openecomp.sdc.tosca.csar;
+
+import static junit.framework.TestCase.assertSame;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+import com.google.common.collect.ImmutableMap;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import org.junit.Before;
+import org.junit.Test;
+import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
+import org.openecomp.sdc.common.errors.Messages;
+
+public class SOL004ManifestOnboardingTest {
+
+    private Manifest manifest;
+
+    @Before
+    public void setUp() {
+        manifest = new SOL004ManifestOnboarding();
+    }
+
+    @Test
+    public void testSuccessfulParsing() throws IOException {
+        try (final InputStream manifestAsStream =
+            getClass().getResourceAsStream("/vspmanager.csar/manifest/ValidTosca.mf")) {
+            manifest.parse(manifestAsStream);
+            assertValidManifest(4, 5, Collections.emptyMap(), ResourceTypeEnum.VF);
+        }
+    }
+
+    @Test
+    public void testNoMetadataParsing() throws IOException {
+        try (final InputStream manifestAsStream = getClass()
+            .getResourceAsStream("/vspmanager.csar/manifest/invalid/no-metadata.mf")) {
+            manifest.parse(manifestAsStream);
+            final List<String> expectedErrorList = new ArrayList<>();
+            expectedErrorList.add(
+                buildErrorMessage(3, "Source: MainServiceTemplate.yaml", Messages.MANIFEST_START_METADATA)
+            );
+            assertInvalidManifest(expectedErrorList);
+        }
+    }
+
+    @Test
+    public void testBrokenMDParsing() throws IOException {
+        try (final InputStream manifestAsStream =
+            getClass().getResourceAsStream("/vspmanager.csar/manifest/InvalidTosca2.mf")) {
+            manifest.parse(manifestAsStream);
+            final List<String> expectedErrorList = new ArrayList<>();
+            expectedErrorList.add(Messages.MANIFEST_INVALID_LINE.formatMessage(9, "vnf_package_version: 1.0"));
+            assertInvalidManifest(expectedErrorList);
+        }
+    }
+
+    @Test
+    public void testNoMetaParsing() throws IOException {
+        try (final InputStream manifestAsStream = getClass()
+            .getResourceAsStream("/vspmanager.csar/manifest/invalid/empty-metadata-with-source.mf")) {
+            manifest.parse(manifestAsStream);
+            final List<String> expectedErrorList = new ArrayList<>();
+            expectedErrorList.add(
+                buildErrorMessage(4, "Source: MainServiceTemplate.yaml",
+                    Messages.MANIFEST_METADATA_INVALID_ENTRY1, "Source: MainServiceTemplate.yaml")
+            );
+            assertInvalidManifest(expectedErrorList);
+        }
+    }
+
+    @Test
+    public void testSuccessfulNonManoParsing() throws IOException {
+        try (final InputStream manifestAsStream = getClass()
+            .getResourceAsStream("/vspmanager.csar/manifest/ValidNonManoTosca.mf")) {
+            manifest.parse(manifestAsStream);
+            assertValidManifest(4, 5,
+                ImmutableMap.of("foo_bar", 3, "prv.happy-nfv.cool", 3), ResourceTypeEnum.VF);
+        }
+    }
+
+    @Test
+    public void testInvalidNonManoParsing() throws IOException {
+        try (final InputStream manifestAsStream = getClass()
+            .getResourceAsStream("/vspmanager.csar/manifest/InValidNonManoTosca.mf")) {
+            manifest.parse(manifestAsStream);
+            final List<String> errorList = Collections.singletonList(
+                buildErrorMessage(34, "vnf_product_name: Mock", Messages.MANIFEST_INVALID_NON_MANO_KEY,
+                    "vnf_product_name")
+            );
+            assertInvalidManifest(errorList);
+        }
+    }
+
+    private String buildErrorMessage(final int lineNumber, final String line, final Messages message,
+                                    final Object... params) {
+        return Messages.MANIFEST_ERROR_WITH_LINE.formatMessage(message.formatMessage(params), lineNumber, line);
+    }
+
+    @Test
+    public void testNonManoParsingWithGarbage() throws IOException {
+        try (final InputStream manifestAsStream = getClass()
+            .getResourceAsStream("/vspmanager.csar/manifest/InvalidToscaNonManoGarbageAtEnd.mf")) {
+            manifest.parse(manifestAsStream);
+            final List<String> errorList = Collections.singletonList(
+                Messages.MANIFEST_ERROR_WITH_LINE.formatMessage(
+                    Messages.MANIFEST_INVALID_NON_MANO_KEY.formatMessage("some garbage"),
+                    34, "some garbage")
+            );
+            assertInvalidManifest(errorList);
+        }
+    }
+
+    @Test
+    public void testInvalidManifestFile() throws IOException {
+        try (final InputStream manifestAsStream = getClass()
+            .getResourceAsStream("/vspmanager.csar/manifest/SOME_WRONG_FILE")) {
+            manifest.parse(manifestAsStream);
+            assertInvalidManifest(Collections.singletonList(Messages.MANIFEST_PARSER_INTERNAL.getErrorMessage()));
+        }
+    }
+
+    @Test
+    public void testManifestSigned() throws IOException {
+        try (final InputStream manifestAsStream = getClass()
+            .getResourceAsStream("/vspmanager.csar/manifest/valid/signed.mf")) {
+            manifest.parse(manifestAsStream);
+            assertValidManifest(4, 3, Collections.emptyMap(), ResourceTypeEnum.VF);
+        }
+    }
+
+    @Test
+    public void testManifestSignedWithNonManoArtifacts() throws IOException {
+        try (final InputStream manifestAsStream = getClass()
+            .getResourceAsStream("/vspmanager.csar/manifest/valid/signed-with-non-mano.mf")) {
+            manifest.parse(manifestAsStream);
+            assertValidManifest(4, 3, ImmutableMap.of("foo_bar", 3), ResourceTypeEnum.VF);
+            manifest.getType().ifPresent(typeEnum -> assertSame(typeEnum, ResourceTypeEnum.VF));
+        }
+    }
+
+    @Test
+    public void testManifestWithPnf() throws IOException {
+        try (final InputStream manifestAsStream = getClass()
+            .getResourceAsStream("/vspmanager.csar/manifest/valid/metadata-pnfd.mf")) {
+            manifest.parse(manifestAsStream);
+            assertValidManifest(4, 3, new HashMap<>(), ResourceTypeEnum.PNF);
+        }
+    }
+
+    @Test
+    public void testMetadataWithNoValue() throws IOException {
+        try (final InputStream manifestAsStream = getClass()
+            .getResourceAsStream("/vspmanager.csar/manifest/invalid/metadata-no-value.mf")) {
+            manifest.parse(manifestAsStream);
+
+            final List<String> expectedErrorList = new ArrayList<>();
+            expectedErrorList.add(
+                buildErrorMessage(3, "vnf_provider_id", Messages.MANIFEST_METADATA_INVALID_ENTRY1, "vnf_provider_id")
+            );
+            assertInvalidManifest(expectedErrorList);
+        }
+    }
+
+    @Test
+    public void testMetadataWithValueButNoEntry() throws IOException {
+        try (final InputStream manifestAsStream = getClass()
+            .getResourceAsStream("/vspmanager.csar/manifest/invalid/metadata-no-entry.mf")) {
+            manifest.parse(manifestAsStream);
+
+            final List<String> expectedErrorList = new ArrayList<>();
+            expectedErrorList.add(
+                buildErrorMessage(3, ": no-entry-value", Messages.MANIFEST_METADATA_INVALID_ENTRY1, ": no-entry-value")
+            );
+            assertInvalidManifest(expectedErrorList);
+        }
+    }
+
+    @Test
+    public void testMetadataWithIncorrectEntry() throws IOException {
+        try (final InputStream manifestAsStream = getClass()
+            .getResourceAsStream("/vspmanager.csar/manifest/invalid/metadata-incorrect-entry.mf")) {
+            manifest.parse(manifestAsStream);
+            final List<String> expectedErrorList = new ArrayList<>();
+            expectedErrorList.add(
+                buildErrorMessage(4, "vnf_release_data_time: 2019-08-29T22:17:39.275281",
+                    Messages.MANIFEST_METADATA_INVALID_ENTRY1, "vnf_release_data_time: 2019-08-29T22:17:39.275281")
+            );
+            assertInvalidManifest(expectedErrorList);
+        }
+    }
+
+    @Test
+    public void testMetadataWithMixedEntries() throws IOException {
+        try (final InputStream manifestAsStream = getClass()
+            .getResourceAsStream("/vspmanager.csar/manifest/invalid/metadata-mixed-entries.mf")) {
+            manifest.parse(manifestAsStream);
+            final List<String> expectedErrorList = new ArrayList<>();
+            expectedErrorList.add(buildErrorMessage(6, "", Messages.MANIFEST_METADATA_UNEXPECTED_ENTRY_TYPE));
+            assertInvalidManifest(expectedErrorList);
+        }
+    }
+
+    @Test
+    public void testMetadataWithDuplicatedEntries() throws IOException {
+        try (final InputStream manifestAsStream =
+            getClass().getResourceAsStream("/vspmanager.csar/manifest/invalid/metadata-duplicated-entries.mf")) {
+            manifest.parse(manifestAsStream);
+            final List<String> expectedErrorList = new ArrayList<>();
+            expectedErrorList.add(
+                buildErrorMessage(4, "vnf_product_name: vPP", Messages.MANIFEST_METADATA_DUPLICATED_ENTRY,
+                    "vnf_product_name")
+            );
+            assertInvalidManifest(expectedErrorList);
+        }
+    }
+
+    @Test
+    public void testManifestNonManoKeyWithoutSources() throws IOException {
+        try (final InputStream manifestAsStream =
+            getClass().getResourceAsStream("/vspmanager.csar/manifest/invalid/non-mano-key-with-no-sources.mf")) {
+            manifest.parse(manifestAsStream);
+            final List<String> expectedErrorList = new ArrayList<>();
+            expectedErrorList.add(
+                buildErrorMessage(11, "", Messages.MANIFEST_EMPTY_NON_MANO_KEY,
+                    "foo_bar")
+            );
+            assertInvalidManifest(expectedErrorList);
+        }
+    }
+
+    @Test
+    public void testManifestNonManoKeyWithEmptySourceEntry() throws IOException {
+        try (final InputStream manifestAsStream =
+            getClass().getResourceAsStream("/vspmanager.csar/manifest/invalid/non-mano-key-with-empty-source.mf")) {
+            manifest.parse(manifestAsStream);
+            final List<String> expectedErrorList = new ArrayList<>();
+            expectedErrorList.add(
+                buildErrorMessage(11, "Source:", Messages.MANIFEST_EMPTY_NON_MANO_SOURCE)
+            );
+            assertInvalidManifest(expectedErrorList);
+        }
+    }
+
+    @Test
+    public void testManifestWithEmptyMetadata() throws IOException {
+        try (final InputStream manifestAsStream =
+            getClass().getResourceAsStream("/vspmanager.csar/manifest/invalid/empty-metadata.mf")) {
+            manifest.parse(manifestAsStream);
+            final List<String> expectedErrorList = new ArrayList<>();
+            expectedErrorList.add(buildErrorMessage(2, "", Messages.MANIFEST_NO_METADATA));
+            assertInvalidManifest(expectedErrorList);
+        }
+    }
+
+    @Test
+    public void testManifestSourceAlgorithmWithoutHash() throws IOException {
+        try (final InputStream manifestAsStream =
+            getClass().getResourceAsStream("/vspmanager.csar/manifest/invalid/source-algorithm-without-hash.mf")) {
+            manifest.parse(manifestAsStream);
+            final List<String> expectedErrorList = new ArrayList<>();
+            expectedErrorList.add(buildErrorMessage(9, "", Messages.MANIFEST_EXPECTED_HASH_ENTRY));
+            assertInvalidManifest(expectedErrorList);
+        }
+    }
+
+    @Test
+    public void testManifestSourceHashWithoutAlgorithm() throws IOException {
+        try (final InputStream manifestAsStream =
+            getClass().getResourceAsStream("/vspmanager.csar/manifest/invalid/source-hash-without-algorithm.mf")) {
+            manifest.parse(manifestAsStream);
+            final List<String> expectedErrorList = new ArrayList<>();
+            expectedErrorList.add(buildErrorMessage(8, "Hash: 3b119b37da5b76ec7c933168b21cedd8", Messages.MANIFEST_EXPECTED_ALGORITHM_BEFORE_HASH));
+            assertInvalidManifest(expectedErrorList);
+        }
+    }
+
+    @Test
+    public void testManifestSourceAlgorithmWithoutValue() throws IOException {
+        try (final InputStream manifestAsStream =
+            getClass().getResourceAsStream("/vspmanager.csar/manifest/invalid/source-algorithm-without-value.mf")) {
+            manifest.parse(manifestAsStream);
+            final List<String> expectedErrorList = new ArrayList<>();
+            expectedErrorList.add(buildErrorMessage(8, "Algorithm:", Messages.MANIFEST_EXPECTED_ALGORITHM_VALUE));
+            assertInvalidManifest(expectedErrorList);
+        }
+    }
+
+    @Test
+    public void testManifestSourceHashWithoutValue() throws IOException {
+        try (final InputStream manifestAsStream =
+            getClass().getResourceAsStream("/vspmanager.csar/manifest/invalid/source-hash-without-value.mf")) {
+            manifest.parse(manifestAsStream);
+            final List<String> expectedErrorList = new ArrayList<>();
+            expectedErrorList.add(buildErrorMessage(9, "Hash:", Messages.MANIFEST_EXPECTED_HASH_VALUE));
+            assertInvalidManifest(expectedErrorList);
+        }
+    }
+
+    @Test
+    public void testEmptyManifest() throws IOException {
+        try (final InputStream manifestAsStream =
+            getClass().getResourceAsStream("/vspmanager.csar/manifest/invalid/empty-manifest.mf")) {
+            manifest.parse(manifestAsStream);
+            final List<String> expectedErrorList = new ArrayList<>();
+            expectedErrorList.add(Messages.MANIFEST_EMPTY.getErrorMessage());
+            assertInvalidManifest(expectedErrorList);
+        }
+    }
+
+    @Test
+    public void testManifestWithDuplicatedCmsSignature() throws IOException {
+        try (final InputStream manifestAsStream =
+            getClass().getResourceAsStream("/vspmanager.csar/manifest/invalid/double-signed.mf")) {
+            manifest.parse(manifestAsStream);
+            final List<String> expectedErrorList = new ArrayList<>();
+            expectedErrorList
+                .add(buildErrorMessage(26, "-----BEGIN CMS-----", Messages.MANIFEST_DUPLICATED_CMS_SIGNATURE));
+            assertInvalidManifest(expectedErrorList);
+        }
+    }
+
+
+    @Test
+    public void testGetEntry() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        final Method getEntryMethod = AbstractOnboardingManifest.class.getDeclaredMethod("readEntryName", String.class);
+        getEntryMethod.setAccessible(true);
+        final Optional<String> noEntry = (Optional<String>) getEntryMethod.invoke(manifest, ":");
+        assertThat("Entry should not be present", noEntry.isPresent(), is(false));
+
+        final Optional<String> blankEntry = (Optional<String>) getEntryMethod.invoke(manifest, "        :");
+        assertThat("Entry should not be present", blankEntry.isPresent(), is(false));
+
+        final Optional<String> noColon = (Optional<String>) getEntryMethod.invoke(manifest, "anyKeyWithoutColon   ");
+        assertThat("Entry should not be present", noColon.isPresent(), is(false));
+
+        final Optional<String> blank = (Optional<String>) getEntryMethod.invoke(manifest, "   ");
+        assertThat("Entry should not be present", blank.isPresent(), is(false));
+
+        final Optional<String> empty = (Optional<String>) getEntryMethod.invoke(manifest, "");
+        assertThat("Entry should not be present", empty.isPresent(), is(false));
+
+        final Optional<String> nul1 = (Optional<String>) getEntryMethod.invoke(manifest, new Object[]{null});
+        assertThat("Entry should not be present", nul1.isPresent(), is(false));
+
+        final Optional<String> entry = (Optional<String>) getEntryMethod
+            .invoke(manifest, "      entry to     test     :       : a value ::: test test:   ");
+        assertThat("Entry should be present", entry.isPresent(), is(true));
+        assertThat("Entry should be as expected", entry.get(), equalTo("entry to     test"));
+    }
+
+    @Test
+    public void testGetValue() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        final Method getValueMethod = AbstractOnboardingManifest.class.getDeclaredMethod("readEntryValue", String.class);
+        getValueMethod.setAccessible(true);
+        final Optional<String> noValue = (Optional<String>) getValueMethod.invoke(manifest, ":");
+        assertThat("Value should not be present", noValue.isPresent(), is(false));
+
+        final Optional<String> blankValue = (Optional<String>) getValueMethod.invoke(manifest, ":          ");
+        assertThat("Value should not be present", blankValue.isPresent(), is(false));
+
+        final Optional<String> noColon = (Optional<String>) getValueMethod.invoke(manifest, "anyKeyWithoutColon   ");
+        assertThat("Value should not be present", noColon.isPresent(), is(false));
+
+        final Optional<String> blank = (Optional<String>) getValueMethod.invoke(manifest, "   ");
+        assertThat("Value should not be present", blank.isPresent(), is(false));
+
+        final Optional<String> empty = (Optional<String>) getValueMethod.invoke(manifest, "");
+        assertThat("Value should not be present", empty.isPresent(), is(false));
+
+        final Optional<String> nul1 = (Optional<String>) getValueMethod.invoke(manifest, new Object[]{null});
+        assertThat("Value should not be present", nul1.isPresent(), is(false));
+
+        final Optional<String> value = (Optional<String>) getValueMethod
+            .invoke(manifest, "attribute     :       : a value ::: test test:   ");
+        assertThat("Value should be present", value.isPresent(), is(true));
+        assertThat("Value should be as expected", value.get(), equalTo(": a value ::: test test:"));
+    }
+
+    private void assertValidManifest(final int expectedMetadataSize, final int expectedSourcesSize,
+                                     final Map<String, Integer> expectedNonManoKeySize,
+                                     final ResourceTypeEnum resourceType) {
+        assertThat("Should have no errors", manifest.getErrors(), is(empty()));
+        assertThat("Should be valid", manifest.isValid(), is(true));
+        assertThat("Metadata should have the expected size",
+            manifest.getMetadata().keySet(), hasSize(expectedMetadataSize));
+        assertThat("Sources should have the expected size", manifest.getSources(), hasSize(expectedSourcesSize));
+        assertThat("Non Mano Sources keys should have the expected size",
+            manifest.getNonManoSources().keySet(), hasSize(expectedNonManoKeySize.keySet().size()));
+        for (final Entry<String, Integer> nonManoKeyAndSize : expectedNonManoKeySize.entrySet()) {
+            final String nonManoKey = nonManoKeyAndSize.getKey();
+            assertThat("Should contain expected Non Mano Sources key",
+                manifest.getNonManoSources().keySet(), hasItem(nonManoKey));
+            assertThat(String.format("Non Mano Sources keys %s should have the expected sources size", nonManoKey),
+                manifest.getNonManoSources().get(nonManoKey).size(), equalTo(nonManoKeyAndSize.getValue()));
+        }
+        assertThat("Should have a type", manifest.getType().isPresent(), is(true));
+        assertThat("Type should be as expected", manifest.getType().get(), equalTo(resourceType));
+    }
+
+    private void assertInvalidManifest(final List<String> expectedErrorList) {
+        assertThat("Should be invalid", manifest.isValid(), is(false));
+        assertThat("Should have the expected error quantity", manifest.getErrors(), hasSize(expectedErrorList.size()));
+        assertThat("Should have expected errors", manifest.getErrors(),
+            containsInAnyOrder(expectedErrorList.toArray(new String[0])));
+    }
+}
index 9cced6b..02215a6 100644 (file)
@@ -2,7 +2,7 @@ metadata:
     vnf_product_name: Mock
     vnf_provider_id: ZTE
     vnf_package_version: 1.0
-    vnf_release_data_time: 2017.01.01T10:00+03:00
+    vnf_release_date_time: 2017.01.01T10:00+03:00
 
 Source: MainServiceTemplate.yaml
 
index 057f548..54bb5cd 100644 (file)
@@ -1,11 +1,13 @@
 metadata:
     vnf_product_name: Mock
     vnf_provider_id: ZTE
+    vnf_package_version: 1.0
+    vnf_release_date_time: 2017.01.01T10:00+03:00
 
 Source: MainServiceTemplate.yaml
 
     vnf_package_version: 1.0
-    vnf_release_data_time: 2017.01.01T10:00+03:00
+    vnf_release_date_time: 2017.01.01T10:00+03:00
 
 
 
index 64e9445..060207f 100644 (file)
@@ -2,6 +2,6 @@ metadata:
     vnf_product_name: Mock
     vnf_provider_id: ZTE
     vnf_package_version: 1.0
-    vnf_release_data_time: 2017.01.01T10:00+03:00
+    vnf_release_date_time: 2017.01.01T10:00+03:00
 
 
@@ -2,7 +2,7 @@ metadata:
     vnf_product_name: Mock
     vnf_provider_id: ZTE
     vnf_package_version: 1.0
-    vnf_release_data_time: 2017.01.01T10:00+03:00
+    vnf_release_date_time: 2017.01.01T10:00+03:00
 
 Source: MainServiceTemplate.yaml
 
@@ -31,4 +31,4 @@ non_mano_artifact_sets:
       Source:   happy/cool/hot/hot_or_cool.json
 
 
-some garbadge
\ No newline at end of file
+some garbage
\ No newline at end of file
index 25ec14c..03f2b3c 100644 (file)
@@ -2,7 +2,7 @@ metadata:
     vnf_product_name: Mock
     vnf_provider_id: ZTE
     vnf_package_version: 1.0
-    vnf_release_data_time: 2017.01.01T10:00+03:00
+    vnf_release_date_time: 2017.01.01T10:00+03:00
 
 Source: MainServiceTemplate.yaml
 
index b2accb7..b9d3844 100644 (file)
@@ -2,7 +2,7 @@ metadata:
     vnf_product_name: Mock
     vnf_provider_id: ZTE
     vnf_package_version: 1.0
-    vnf_release_data_time: 2017.01.01T10:00+03:00
+    vnf_release_date_time: 2017.01.01T10:00+03:00
 
 Source: MainServiceTemplate.yaml
 
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/double-signed.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/double-signed.mf
new file mode 100644 (file)
index 0000000..88098a1
--- /dev/null
@@ -0,0 +1,35 @@
+metadata:
+  vnf_product_name: vPP
+  vnf_provider_id: Ericsson
+  vnf_package_version: R24A583
+  vnf_release_date_time: 2019-08-29T22:17:39.275281
+
+Source: scripts/userdata.file
+Algorithm: md5
+Hash: 3b119b37da5b76ec7c933168b21cedd8
+
+-----BEGIN CMS-----
+MIIBcwYJKoZIhvcNAQcCoIIBZDCCAWACAQMxDTALBglghkgBZQMEAgEwCwYJKoZI
+hvcNAQcBMYIBPTCCATkCAQOAFGOGMKMvLSRzUBjkgZipSoZm1U/UMAsGCWCGSAFl
+AwQCATANBgkqhkiG9w0BAQEFAASCAQBNHXz1p5NBM9Nlvp8RPoVjszzh9UfQ/OCp
+mB926MTLexWOiawjPRKuoiXn4y4dQFZBXauunCOyXYfPASUMFnhL/7gvhajPH25/
+MwEyEsUqsCyJ63tAeYxZAqTZWA2pZi9ejCPoRnt6xl7EhEyogXiSBgc2P89hxhe6
+0/MP6Mtw9D8Ks7M1LxH6ntxGApPTNRlmMtQkrx/ZUtAcKKZJoNpofzdmd+O60PMT
+igNsuwzMNy5LfSjvp8xgWoxhWr4/zLRIZ5F5Z5qhz7lia9xDSGYMfPitDCVqI9XE
+O58S/FoHu+z3Tig7vauTFFbiJjIu9SkG0c33ayEUCKejuVQPjuY9
+-----END CMS-----
+
+Source: scripts/userdata.file.sm
+Algorithm: md5
+Hash: 3b119b37da5b76ec7c933168b21cedd7
+
+-----BEGIN CMS-----
+MIIBcwYJKoZIhvcNAQcCoIIBZDCCAWACAQMxDTALBglghkgBZQMEAgEwCwYJKoZI
+hvcNAQcBMYIBPTCCATkCAQOAFGOGMKMvLSRzUBjkgZipSoZm1U/UMAsGCWCGSAFl
+AwQCATANBgkqhkiG9w0BAQEFAASCAQBNHXz1p5NBM9Nlvp8RPoVjszzh9UfQ/OCp
+mB926MTLexWOiawjPRKuoiXn4y4dQFZBXauunCOyXYfPASUMFnhL/7gvhajPH25/
+MwEyEsUqsCyJ63tAeYxZAqTZWA2pZi9ejCPoRnt6xl7EhEyogXiSBgc2P89hxhe6
+0/MP6Mtw9D8Ks7M1LxH6ntxGApPTNRlmMtQkrx/ZUtAcKKZJoNpofzdmd+O60PMT
+igNsuwzMNy5LfSjvp8xgWoxhWr4/zLRIZ5F5Z5qhz7lia9xDSGYMfPitDCVqI9XE
+O58S/FoHu+z3Tig7vauTFFbiJjIu9SkG0c33ayEUCKejuVQPjuY9
+-----END CMS-----
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/empty-manifest.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/empty-manifest.mf
new file mode 100644 (file)
index 0000000..3f2ff2d
--- /dev/null
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/empty-metadata.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/empty-metadata.mf
new file mode 100644 (file)
index 0000000..7b518cb
--- /dev/null
@@ -0,0 +1 @@
+metadata:
\ No newline at end of file
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/metadata-duplicated-entries.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/metadata-duplicated-entries.mf
new file mode 100644 (file)
index 0000000..696265e
--- /dev/null
@@ -0,0 +1,4 @@
+metadata:
+  vnf_product_name: vPP
+  vnf_provider_id: Ericsson
+  vnf_product_name: vPP
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/metadata-incorrect-entry.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/metadata-incorrect-entry.mf
new file mode 100644 (file)
index 0000000..139e18e
--- /dev/null
@@ -0,0 +1,5 @@
+metadata:
+  vnf_product_name: vPP
+  vnf_provider_id: Ericsson
+  vnf_release_data_time: 2019-08-29T22:17:39.275281
+  vnf_package_version: R24A583
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/metadata-mixed-entries.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/metadata-mixed-entries.mf
new file mode 100644 (file)
index 0000000..0d26e2d
--- /dev/null
@@ -0,0 +1,5 @@
+metadata:
+  vnf_product_name: vPP
+  vnf_provider_id: Ericsson
+  vnf_release_date_time: 2019-08-29T22:17:39.275281
+  pnfd_archive_version: 1.0
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/metadata-no-entry.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/metadata-no-entry.mf
new file mode 100644 (file)
index 0000000..bc6db7e
--- /dev/null
@@ -0,0 +1,3 @@
+metadata:
+  vnf_product_name: vPP
+  : no-entry-value
\ No newline at end of file
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/metadata-no-value.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/metadata-no-value.mf
new file mode 100644 (file)
index 0000000..9d286d6
--- /dev/null
@@ -0,0 +1,3 @@
+metadata:
+  vnf_product_name: vPP
+  vnf_provider_id
\ No newline at end of file
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/non-mano-key-with-empty-source.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/non-mano-key-with-empty-source.mf
new file mode 100644 (file)
index 0000000..e4544d4
--- /dev/null
@@ -0,0 +1,11 @@
+metadata:
+  vnf_product_name: vPP
+  vnf_provider_id: Ericsson
+  vnf_package_version: R24A583
+  vnf_release_date_time: 2019-08-29T22:17:39.275281
+
+Source: scripts/userdata.file.sm
+
+non_mano_artifact_sets:
+  foo_bar:
+    Source:
\ No newline at end of file
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/non-mano-key-with-no-sources.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/non-mano-key-with-no-sources.mf
new file mode 100644 (file)
index 0000000..a7533bb
--- /dev/null
@@ -0,0 +1,10 @@
+metadata:
+  vnf_product_name: vPP
+  vnf_provider_id: Ericsson
+  vnf_package_version: R24A583
+  vnf_release_date_time: 2019-08-29T22:17:39.275281
+
+Source: scripts/userdata.file.sm
+
+non_mano_artifact_sets:
+  foo_bar:
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/source-algorithm-without-hash.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/source-algorithm-without-hash.mf
new file mode 100644 (file)
index 0000000..a9a9887
--- /dev/null
@@ -0,0 +1,8 @@
+metadata:
+  vnf_product_name: vPP
+  vnf_provider_id: Ericsson
+  vnf_package_version: R24A583
+  vnf_release_date_time: 2019-08-29T22:17:39.275281
+
+Source: scripts/userdata.file.sm
+Algorithm: md5
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/source-algorithm-without-value.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/source-algorithm-without-value.mf
new file mode 100644 (file)
index 0000000..79797d7
--- /dev/null
@@ -0,0 +1,9 @@
+metadata:
+  vnf_product_name: vPP
+  vnf_provider_id: Ericsson
+  vnf_package_version: R24A583
+  vnf_release_date_time: 2019-08-29T22:17:39.275281
+
+Source: scripts/userdata.file.sm
+Algorithm:
+Hash: 3b119b37da5b76ec7c933168b21cedd8
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/source-hash-without-algorithm.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/source-hash-without-algorithm.mf
new file mode 100644 (file)
index 0000000..ec10bc8
--- /dev/null
@@ -0,0 +1,8 @@
+metadata:
+  vnf_product_name: vPP
+  vnf_provider_id: Ericsson
+  vnf_package_version: R24A583
+  vnf_release_date_time: 2019-08-29T22:17:39.275281
+
+Source: scripts/userdata.file.sm
+Hash: 3b119b37da5b76ec7c933168b21cedd8
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/source-hash-without-value.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/invalid/source-hash-without-value.mf
new file mode 100644 (file)
index 0000000..2d786f1
--- /dev/null
@@ -0,0 +1,9 @@
+metadata:
+  vnf_product_name: vPP
+  vnf_provider_id: Ericsson
+  vnf_package_version: R24A583
+  vnf_release_date_time: 2019-08-29T22:17:39.275281
+
+Source: scripts/userdata.file.sm
+Algorithm: md5
+Hash:
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/valid/metadata-pnfd.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/valid/metadata-pnfd.mf
new file mode 100644 (file)
index 0000000..8bf73ed
--- /dev/null
@@ -0,0 +1,27 @@
+metadata:
+  pnfd_name: Name
+  pnfd_provider: Provider
+  pnfd_archive_version: 1.0
+  pnfd_release_date_time: 2017-01-01T10:00:00+03:00
+
+Source: TOSCA-Metadata/TOSCA.meta
+
+Source: scripts/userdata.file
+Algorithm: md5
+Hash: 3b119b37da5b76ec7c933168b21cedd8
+
+Source: scripts/userdata.file.sm
+
+
+
+
+-----BEGIN CMS-----
+MIIBcwYJKoZIhvcNAQcCoIIBZDCCAWACAQMxDTALBglghkgBZQMEAgEwCwYJKoZI
+hvcNAQcBMYIBPTCCATkCAQOAFGOGMKMvLSRzUBjkgZipSoZm1U/UMAsGCWCGSAFl
+AwQCATANBgkqhkiG9w0BAQEFAASCAQBNHXz1p5NBM9Nlvp8RPoVjszzh9UfQ/OCp
+mB926MTLexWOiawjPRKuoiXn4y4dQFZBXauunCOyXYfPASUMFnhL/7gvhajPH25/
+MwEyEsUqsCyJ63tAeYxZAqTZWA2pZi9ejCPoRnt6xl7EhEyogXiSBgc2P89hxhe6
+0/MP6Mtw9D8Ks7M1LxH6ntxGApPTNRlmMtQkrx/ZUtAcKKZJoNpofzdmd+O60PMT
+igNsuwzMNy5LfSjvp8xgWoxhWr4/zLRIZ5F5Z5qhz7lia9xDSGYMfPitDCVqI9XE
+O58S/FoHu+z3Tig7vauTFFbiJjIu9SkG0c33ayEUCKejuVQPjuY9
+-----END CMS-----
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/valid/signed-with-non-mano.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/valid/signed-with-non-mano.mf
new file mode 100644 (file)
index 0000000..dee6384
--- /dev/null
@@ -0,0 +1,30 @@
+metadata:
+  vnf_product_name: vPP
+  vnf_provider_id: Ericsson
+  vnf_package_version: R24A583
+  vnf_release_date_time: 2019-08-29T22:17:39.275281
+
+Source: TOSCA-Metadata/TOSCA.meta
+
+Source: scripts/userdata.file
+Algorithm: md5
+Hash: 3b119b37da5b76ec7c933168b21cedd8
+
+Source: scripts/userdata.file.sm
+
+-----BEGIN CMS-----
+MIIBcwYJKoZIhvcNAQcCoIIBZDCCAWACAQMxDTALBglghkgBZQMEAgEwCwYJKoZI
+hvcNAQcBMYIBPTCCATkCAQOAFGOGMKMvLSRzUBjkgZipSoZm1U/UMAsGCWCGSAFl
+AwQCATANBgkqhkiG9w0BAQEFAASCAQBNHXz1p5NBM9Nlvp8RPoVjszzh9UfQ/OCp
+mB926MTLexWOiawjPRKuoiXn4y4dQFZBXauunCOyXYfPASUMFnhL/7gvhajPH25/
+MwEyEsUqsCyJ63tAeYxZAqTZWA2pZi9ejCPoRnt6xl7EhEyogXiSBgc2P89hxhe6
+0/MP6Mtw9D8Ks7M1LxH6ntxGApPTNRlmMtQkrx/ZUtAcKKZJoNpofzdmd+O60PMT
+igNsuwzMNy5LfSjvp8xgWoxhWr4/zLRIZ5F5Z5qhz7lia9xDSGYMfPitDCVqI9XE
+O58S/FoHu+z3Tig7vauTFFbiJjIu9SkG0c33ayEUCKejuVQPjuY9
+-----END CMS-----
+
+non_mano_artifact_sets:
+  foo_bar:
+    Source: foobar/foo/foo.yaml
+    Source: foobar/foo/foo.script
+    Source: foobar/bar/descriptor.xml
diff --git a/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/valid/signed.mf b/openecomp-be/lib/openecomp-tosca-lib/src/test/resources/vspmanager.csar/manifest/valid/signed.mf
new file mode 100644 (file)
index 0000000..fe43239
--- /dev/null
@@ -0,0 +1,27 @@
+metadata:
+  vnf_product_name: vPP
+  vnf_provider_id: Ericsson
+  vnf_package_version: R24A583
+  vnf_release_date_time: 2019-08-29T22:17:39.275281
+
+Source: TOSCA-Metadata/TOSCA.meta
+
+Source: scripts/userdata.file
+Algorithm: md5
+Hash: 3b119b37da5b76ec7c933168b21cedd8
+
+Source: scripts/userdata.file.sm
+
+
+
+
+-----BEGIN CMS-----
+MIIBcwYJKoZIhvcNAQcCoIIBZDCCAWACAQMxDTALBglghkgBZQMEAgEwCwYJKoZI
+hvcNAQcBMYIBPTCCATkCAQOAFGOGMKMvLSRzUBjkgZipSoZm1U/UMAsGCWCGSAFl
+AwQCATANBgkqhkiG9w0BAQEFAASCAQBNHXz1p5NBM9Nlvp8RPoVjszzh9UfQ/OCp
+mB926MTLexWOiawjPRKuoiXn4y4dQFZBXauunCOyXYfPASUMFnhL/7gvhajPH25/
+MwEyEsUqsCyJ63tAeYxZAqTZWA2pZi9ejCPoRnt6xl7EhEyogXiSBgc2P89hxhe6
+0/MP6Mtw9D8Ks7M1LxH6ntxGApPTNRlmMtQkrx/ZUtAcKKZJoNpofzdmd+O60PMT
+igNsuwzMNy5LfSjvp8xgWoxhWr4/zLRIZ5F5Z5qhz7lia9xDSGYMfPitDCVqI9XE
+O58S/FoHu+z3Tig7vauTFFbiJjIu9SkG0c33ayEUCKejuVQPjuY9
+-----END CMS-----