2  * Copyright © 2017-2018 AT&T Intellectual Property.
 
   3  * Modifications Copyright © 2019 Bell Canada.
 
   4  * Modifications Copyright © 2019 IBM.
 
   6  * Licensed under the Apache License, Version 2.0 (the "License");
 
   7  * you may not use this file except in compliance with the License.
 
   8  * You may obtain a copy of the License at
 
  10  *     http://www.apache.org/licenses/LICENSE-2.0
 
  12  * Unless required by applicable law or agreed to in writing, software
 
  13  * distributed under the License is distributed on an "AS IS" BASIS,
 
  14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  15  * See the License for the specific language governing permissions and
 
  16  * limitations under the License.
 
  19 package org.onap.ccsdk.apps.controllerblueprints.service.utils
 
  21 import kotlinx.coroutines.Dispatchers
 
  22 import kotlinx.coroutines.reactive.awaitSingle
 
  23 import kotlinx.coroutines.withContext
 
  24 import org.apache.commons.io.FileUtils
 
  25 import org.onap.ccsdk.apps.controllerblueprints.core.BluePrintException
 
  26 import org.onap.ccsdk.apps.controllerblueprints.core.data.*
 
  27 import org.onap.ccsdk.apps.controllerblueprints.core.deCompress
 
  28 import org.onap.ccsdk.apps.controllerblueprints.core.interfaces.BluePrintRepoService
 
  29 import org.onap.ccsdk.apps.controllerblueprints.core.reCreateDirs
 
  30 import org.onap.ccsdk.apps.controllerblueprints.core.service.BluePrintContext
 
  31 import org.onap.ccsdk.apps.controllerblueprints.core.utils.BluePrintArchiveUtils
 
  32 import org.springframework.core.io.ByteArrayResource
 
  33 import org.springframework.core.io.Resource
 
  34 import org.springframework.http.HttpHeaders
 
  35 import org.springframework.http.MediaType
 
  36 import org.springframework.http.ResponseEntity
 
  37 import org.springframework.http.codec.multipart.FilePart
 
  38 import org.springframework.util.StringUtils
 
  39 import reactor.core.publisher.Mono
 
  41 import java.io.IOException
 
  42 import java.nio.file.Path
 
  43 import java.nio.file.Paths
 
  47 class BluePrintEnhancerUtils {
 
  50         fun populateDataTypes(bluePrintContext: BluePrintContext, bluePrintRepoService: BluePrintRepoService,
 
  51                               dataTypeName: String): DataType {
 
  52             val dataType = bluePrintContext.serviceTemplate.dataTypes?.get(dataTypeName)
 
  53                     ?: bluePrintRepoService.getDataType(dataTypeName)
 
  54                     ?: throw BluePrintException("couldn't get DataType($dataTypeName) from repo.")
 
  55             bluePrintContext.serviceTemplate.dataTypes?.put(dataTypeName, dataType)
 
  59         fun populateRelationshipType(bluePrintContext: BluePrintContext, bluePrintRepoService: BluePrintRepoService,
 
  60                                      relationshipName: String): RelationshipType {
 
  62             val relationshipType = bluePrintContext.serviceTemplate.relationshipTypes?.get(relationshipName)
 
  63                     ?: bluePrintRepoService.getRelationshipType(relationshipName)
 
  64                     ?: throw BluePrintException("couldn't get RelationshipType($relationshipName) from repo.")
 
  65             bluePrintContext.serviceTemplate.relationshipTypes?.put(relationshipName, relationshipType)
 
  66             return relationshipType
 
  70         fun populateNodeType(bluePrintContext: BluePrintContext, bluePrintRepoService: BluePrintRepoService,
 
  71                              nodeTypeName: String): NodeType {
 
  73             val nodeType = bluePrintContext.serviceTemplate.nodeTypes?.get(nodeTypeName)
 
  74                     ?: bluePrintRepoService.getNodeType(nodeTypeName)
 
  75                     ?: throw BluePrintException("couldn't get NodeType($nodeTypeName) from repo.")
 
  76             bluePrintContext.serviceTemplate.nodeTypes?.put(nodeTypeName, nodeType)
 
  80         fun populateArtifactType(bluePrintContext: BluePrintContext, bluePrintRepoService: BluePrintRepoService,
 
  81                                  artifactTypeName: String): ArtifactType {
 
  83             val artifactType = bluePrintContext.serviceTemplate.artifactTypes?.get(artifactTypeName)
 
  84                     ?: bluePrintRepoService.getArtifactType(artifactTypeName)
 
  85                     ?: throw BluePrintException("couldn't get ArtifactType($artifactTypeName) from repo.")
 
  86             bluePrintContext.serviceTemplate.artifactTypes?.put(artifactTypeName, artifactType)
 
  90         suspend fun copyFromFilePart(filePart: FilePart, targetFile: File): File {
 
  91             // Delete the Directory
 
  92             targetFile.deleteRecursively()
 
  93             return filePart.transferTo(targetFile)
 
  94                     .thenReturn(targetFile)
 
  98         suspend fun decompressFilePart(filePart: FilePart, archiveDir: String, enhanceDir: String): File {
 
  99             //Recreate the Base Directories
 
 100             Paths.get(archiveDir).toFile().reCreateDirs()
 
 101             Paths.get(enhanceDir).toFile().reCreateDirs()
 
 103             val filePartFile = Paths.get(archiveDir, "cba.zip").toFile()
 
 104             // Copy the File Part to ZIP
 
 105             copyFromFilePart(filePart, filePartFile)
 
 106             val deCompressFileName = Paths.get(enhanceDir).toUri().path
 
 107             return filePartFile.deCompress(deCompressFileName)
 
 110         suspend fun compressToFilePart(enhanceDir: String, archiveDir: String): ResponseEntity<Resource> {
 
 111             val compressedFile = Paths.get(archiveDir, "enhanced-cba.zip").toFile()
 
 112             BluePrintArchiveUtils.compress(Paths.get(enhanceDir).toFile(), compressedFile, true)
 
 113             return prepareResourceEntity(compressedFile.name, compressedFile.readBytes())
 
 116         suspend fun prepareResourceEntity(fileName: String, file: ByteArray): ResponseEntity<Resource> {
 
 117             return ResponseEntity.ok()
 
 118                     .contentType(MediaType.parseMediaType("text/plain"))
 
 119                     .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"$fileName\"")
 
 120                     .body(ByteArrayResource(file))
 
 123         suspend fun cleanEnhancer(archiveLocation: String, enhancementLocation: String) = withContext(Dispatchers.Default) {
 
 124             val enrichDir = File(enhancementLocation)
 
 125             FileUtils.forceDeleteOnExit(enrichDir)
 
 127             val archiveDir = File(archiveLocation)
 
 128             FileUtils.forceDeleteOnExit(archiveDir)
 
 132          * This is a saveCBAFile method
 
 133          * take a [FilePart], transfer it to disk using a Flux of FilePart and return a [Mono] representing the CBA file name
 
 135          * @param (filePart, targetDirectory) - the request part containing the file to be saved and the default directory where to save
 
 136          * @return a [Mono] String representing the result of the operation
 
 137          * @throws (BluePrintException, IOException) BluePrintException, IOException
 
 139         @Throws(BluePrintException::class, IOException::class)
 
 140         fun saveCBAFile(filePart: FilePart, targetDirectory: Path): Mono<String> {
 
 142             // Normalize file name
 
 143             val fileName = StringUtils.cleanPath(filePart.filename())
 
 145             // Check if the file's extension is "CBA"
 
 146             if (StringUtils.getFilenameExtension(fileName) != "zip") {
 
 147                 throw BluePrintException(ErrorCode.INVALID_FILE_EXTENSION.value, "Invalid file extension required ZIP")
 
 150             // Change file name to match a pattern
 
 151             val changedFileName = UUID.randomUUID().toString() + ".zip"
 
 152             //String changedFileName = BluePrintFileUtils.Companion.getCBAGeneratedFileName(fileName, this.CBA_FILE_NAME_PATTERN);
 
 154             // Copy file to the target location (Replacing existing file with the same name)
 
 155             val targetLocation = targetDirectory.resolve(changedFileName)
 
 157             // if a file with the same name already exists in a repository, delete and recreate it
 
 158             val file = File(targetLocation.toString())
 
 163             return filePart.transferTo(file).thenReturn(changedFileName)