Merge "CDS-SDC Listener application"
diff --git a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerNotificationCallback.java b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerNotificationCallback.java
index 424a738..aaab8d8 100644
--- a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerNotificationCallback.java
+++ b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/CdsSdcListenerNotificationCallback.java
@@ -9,7 +9,8 @@
 package org.onap.ccsdk.cds.cdssdclistener;
 
 import static org.onap.sdc.utils.DistributionActionResultEnum.SUCCESS;
-import java.util.List;
+import java.util.Objects;
+import org.onap.ccsdk.cds.cdssdclistener.service.ListenerServiceImpl;
 import org.onap.sdc.api.IDistributionClient;
 import org.onap.sdc.api.consumer.INotificationCallback;
 import org.onap.sdc.api.notification.IArtifactInfo;
@@ -26,6 +27,9 @@
     @Autowired
     private CdsSdcListenerDto cdsSdcListenerDto;
 
+    @Autowired
+    private ListenerServiceImpl listenerService;
+
     private static final Logger LOGGER = LoggerFactory.getLogger(CdsSdcListenerNotificationCallback.class);
 
     @Override
@@ -35,35 +39,32 @@
     }
 
     private void processNotification(INotificationData notificationData) {
-        downlaodCsarArtifacts(notificationData.getServiceArtifacts());
+        final IDistributionClient distributionClient = cdsSdcListenerDto.getDistributionClient();
+        notificationData.getServiceArtifacts()
+            .forEach(artifactInfo -> downloadCsarArtifacts(artifactInfo, distributionClient));
     }
 
     /**
      * Download the TOSCA CSAR artifact.
-     * @param artifactInfo - An object consists of Artifact information.
+     *
+     * @param info - Artifact information
+     * @param distributionClient - SDC distribution client
      */
-    private void downlaodCsarArtifacts(List<IArtifactInfo> artifactInfo) {
-        final IDistributionClient distributionClient = cdsSdcListenerDto.getDistributionClient();
+    private void downloadCsarArtifacts(IArtifactInfo info, IDistributionClient distributionClient) {
+        final String url = info.getArtifactURL();
+        final String id = info.getArtifactUUID();
+        if (Objects.equals(info.getArtifactType(), CdsSdcListenerConfiguration.TOSCA_CSAR)) {
+            LOGGER.info("Trying to download the artifact from : {} and UUID is {} ", url, id);
 
-        artifactInfo.forEach(info -> {
-            final String url = info.getArtifactURL();
-            final String id = info.getArtifactUUID();
-            if (info.getArtifactType().equals(CdsSdcListenerConfiguration.TOSCA_CSAR)) {
-                LOGGER.info("Trying to download the artifact from : {} and UUID is {} ", url, id);
+            // Download the artifact
+            IDistributionClientDownloadResult result = distributionClient.download(info);
 
-                IDistributionClientDownloadResult result = distributionClient.download(info);
-
-                if (!result.getDistributionActionResult().equals(SUCCESS)) {
-                    LOGGER.info("Failed to download the artifact from : {} due to {} ", url,
-                        result.getDistributionActionResult());
-                } else {
-                    parseCBAFileFromCsar(result);
-                }
+            if (!Objects.equals(result.getDistributionActionResult(), SUCCESS)) {
+                LOGGER.error("Failed to download the artifact from : {} due to {} ", url,
+                    result.getDistributionActionResult());
+            } else {
+                // TODO Store the CSAR into CSARArchive path and extract the Blueprint using ListenerServiceImpl.extractBluePrint
             }
-        });
-    }
-
-    private void parseCBAFileFromCsar(IDistributionClientDownloadResult result) {
-
+        }
     }
 }
diff --git a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerService.java b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerService.java
index 0aa6499..5dc0c21 100644
--- a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerService.java
+++ b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerService.java
@@ -8,11 +8,22 @@
 
 package org.onap.ccsdk.cds.cdssdclistener.service;
 
-import java.io.File;
+import java.util.zip.ZipFile;
 
 public interface ListenerService {
 
-    void extractBluePrint(File file);
+    /**
+     * Get the controller blueprint archive from CSAR package.
+     *
+     * @param csarArchivePath The path where CSAR archive is stored.
+     * @param cbaArchivePath The destination path where CBA will be stored.
+     */
+    void extractBluePrint(String csarArchivePath, String cbaArchivePath);
 
-    void storeBluePrint(File file);
+    /**
+     * Store the Zip file into CDS database.
+     *
+     * @param file The file to be stored.
+     */
+    void saveBluePrintToCdsDatabase(ZipFile file);
 }
diff --git a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerServiceImpl.java b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerServiceImpl.java
index 356b2f4..4ff2a6e 100644
--- a/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerServiceImpl.java
+++ b/ms/cds-sdc-listener/application/src/main/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerServiceImpl.java
@@ -9,19 +9,90 @@
 package org.onap.ccsdk.cds.cdssdclistener.service;
 
 import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Enumeration;
+import java.util.regex.Pattern;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import org.apache.tomcat.util.http.fileupload.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.stereotype.Component;
 
 @Component
+@ConfigurationProperties("listenerservice")
 public class ListenerServiceImpl implements ListenerService {
 
-    @Override
-    public void extractBluePrint(File file) {
-        //TODO
+    @Value("${listenerservice.config.csarArchive}")
+    private String csarArchivePath;
 
+    @Value("${listenerservice.config.cbaArchive}")
+    private String cbaArchivePath;
+
+    private static final String CBA_ZIP_PATH = "Artifacts/Resources/[a-zA-Z0-9-_]+/Deployment/CONTROLLER_BLUEPRINT_ARCHIVE/[a-zA-Z0-9-_]+[.]zip";
+    private static final Logger LOGGER = LoggerFactory.getLogger(ListenerServiceImpl.class);
+
+    @Override
+    public void extractBluePrint(String csarArchivePath, String cbaArchivePath) {
+        Path cbaStorageDir = getStorageDirectory(cbaArchivePath);
+        try (ZipFile zipFile = new ZipFile(csarArchivePath)) {
+            Enumeration<? extends ZipEntry> entries = zipFile.entries();
+            while (entries.hasMoreElements()) {
+                ZipEntry entry = entries.nextElement();
+                String fileName = entry.getName();
+                if (Pattern.matches(CBA_ZIP_PATH, fileName)) {
+                    final String cbaArchiveName = Paths.get(fileName).getFileName().toString();
+                    storeBluePrint(zipFile, cbaArchiveName, cbaStorageDir, entry);
+                }
+            }
+        } catch (Exception e) {
+            LOGGER.error("Failed to extract blueprint", e);
+        }
+    }
+
+    private void storeBluePrint(ZipFile zipFile, String fileName, Path cbaArchivePath, ZipEntry entry) {
+        final String changedFileName = fileName + ".zip";
+        Path targetLocation = cbaArchivePath.resolve(changedFileName);
+        File targetZipFile = new File(targetLocation.toString());
+
+        try {
+            targetZipFile.createNewFile();
+
+        } catch (IOException e) {
+            LOGGER.error("Could not able to create file {}", targetZipFile, e);
+        }
+
+        try (InputStream inputStream = zipFile.getInputStream(entry); OutputStream out = new FileOutputStream(
+            targetZipFile)) {
+            IOUtils.copy(inputStream, out);
+        } catch (Exception e) {
+            LOGGER.error("Failed to put zip file into target location {}", targetLocation, e);
+        }
+    }
+
+    private Path getStorageDirectory(String path) {
+        Path fileStorageLocation = Paths.get(path).toAbsolutePath().normalize();
+
+        if (!Files.exists(fileStorageLocation)) {
+            try {
+                return Files.createDirectories(fileStorageLocation);
+            } catch (IOException e) {
+                LOGGER.error("Fail to create directory", e);
+            }
+        }
+        return fileStorageLocation;
     }
 
     @Override
-    public void storeBluePrint(File file) {
+    public void saveBluePrintToCdsDatabase(ZipFile file) {
         //TODO
     }
 }
diff --git a/ms/cds-sdc-listener/application/src/main/resources/application.yml b/ms/cds-sdc-listener/application/src/main/resources/application.yml
index 1daef58..88de3b1 100644
--- a/ms/cds-sdc-listener/application/src/main/resources/application.yml
+++ b/ms/cds-sdc-listener/application/src/main/resources/application.yml
@@ -14,4 +14,6 @@
       keyStorePath:
       activateServerTLSAuth : false
       isUseHttpsWithDmaap: false
+      csarArchive: /opt/app/onap/cds-sdc-listener/csar-archive
+      cbaArchive: /opt/app/onap/cds/sdc-listener/cba-archive
 
diff --git a/ms/cds-sdc-listener/application/src/test/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerServiceImplTest.java b/ms/cds-sdc-listener/application/src/test/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerServiceImplTest.java
new file mode 100644
index 0000000..05e1ffd
--- /dev/null
+++ b/ms/cds-sdc-listener/application/src/test/java/org/onap/ccsdk/cds/cdssdclistener/service/ListenerServiceImplTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 Bell Canada. All rights reserved.
+ *
+ * NOTICE:  All the intellectual and technical concepts contained herein are
+ * proprietary to Bell Canada and are protected by trade secret or copyright law.
+ * Unauthorized copying of this file, via any medium is strictly prohibited.
+ */
+
+package org.onap.ccsdk.cds.cdssdclistener.service;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@EnableConfigurationProperties(ListenerServiceImpl.class)
+@SpringBootTest(classes = {ListenerServiceImplTest.class})
+public class ListenerServiceImplTest {
+
+    private static final String CSAR_SAMPLE = "src/test/resources/service-Testsvc140.csar";
+    private Path tempDirectoryPath;
+
+    @Rule
+    public TemporaryFolder folder = new TemporaryFolder();
+
+    @Autowired
+    private ListenerServiceImpl listenerService;
+
+    @Test
+    public void extractBluePrintSuccessfully() {
+        // Arrange
+        tempDirectoryPath = Paths.get(folder.getRoot().toString(), "cds-sdc-listener-test");
+
+        // Act
+        listenerService.extractBluePrint(CSAR_SAMPLE, tempDirectoryPath.toString());
+    }
+}
diff --git a/ms/cds-sdc-listener/application/src/test/resources/service-Testsvc140.csar b/ms/cds-sdc-listener/application/src/test/resources/service-Testsvc140.csar
new file mode 100644
index 0000000..4aa0de7
--- /dev/null
+++ b/ms/cds-sdc-listener/application/src/test/resources/service-Testsvc140.csar
Binary files differ