6eab5cd3f7e29e89b4213181b8a60c06acaffac7
[ccsdk/cds.git] /
1 /*
2  * Copyright © 2017-2018 AT&T Intellectual Property.
3  * Modifications Copyright © 2019 Bell Canada.
4  * Modifications Copyright © 2019 IBM.
5  *
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
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19 package org.onap.ccsdk.cds.blueprintsprocessor.designer.api.utils
20
21 import kotlinx.coroutines.Dispatchers
22 import kotlinx.coroutines.reactive.awaitSingle
23 import kotlinx.coroutines.withContext
24 import org.onap.ccsdk.cds.controllerblueprints.core.*
25 import org.onap.ccsdk.cds.controllerblueprints.core.data.*
26 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintRepoService
27 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
28 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintArchiveUtils
29 import org.springframework.core.io.ByteArrayResource
30 import org.springframework.core.io.Resource
31 import org.springframework.http.HttpHeaders
32 import org.springframework.http.MediaType
33 import org.springframework.http.ResponseEntity
34 import org.springframework.http.codec.multipart.FilePart
35 import org.springframework.util.StringUtils
36 import reactor.core.publisher.Mono
37 import java.io.File
38 import java.io.IOException
39 import java.nio.file.Path
40 import java.nio.file.Paths
41 import java.util.*
42
43
44 class BluePrintEnhancerUtils {
45     companion object {
46
47         fun populateDataTypes(bluePrintContext: BluePrintContext, bluePrintRepoService: BluePrintRepoService,
48                               dataTypeName: String): DataType {
49             val dataType = bluePrintContext.serviceTemplate.dataTypes?.get(dataTypeName)
50                     ?: bluePrintRepoService.getDataType(dataTypeName)
51                     ?: throw BluePrintException("couldn't get DataType($dataTypeName) from repo.")
52             bluePrintContext.serviceTemplate.dataTypes?.put(dataTypeName, dataType)
53             return dataType
54         }
55
56         fun populateRelationshipType(bluePrintContext: BluePrintContext, bluePrintRepoService: BluePrintRepoService,
57                                      relationshipName: String): RelationshipType {
58
59             val relationshipType = bluePrintContext.serviceTemplate.relationshipTypes?.get(relationshipName)
60                     ?: bluePrintRepoService.getRelationshipType(relationshipName)
61                     ?: throw BluePrintException("couldn't get RelationshipType($relationshipName) from repo.")
62             bluePrintContext.serviceTemplate.relationshipTypes?.put(relationshipName, relationshipType)
63             return relationshipType
64         }
65
66
67         fun populateNodeType(bluePrintContext: BluePrintContext, bluePrintRepoService: BluePrintRepoService,
68                              nodeTypeName: String): NodeType {
69
70             val nodeType = bluePrintContext.serviceTemplate.nodeTypes?.get(nodeTypeName)
71                     ?: bluePrintRepoService.getNodeType(nodeTypeName)
72                     ?: throw BluePrintException("couldn't get NodeType($nodeTypeName) from repo.")
73             bluePrintContext.serviceTemplate.nodeTypes?.put(nodeTypeName, nodeType)
74             return nodeType
75         }
76
77         fun populateArtifactType(bluePrintContext: BluePrintContext, bluePrintRepoService: BluePrintRepoService,
78                                  artifactTypeName: String): ArtifactType {
79
80             val artifactType = bluePrintContext.serviceTemplate.artifactTypes?.get(artifactTypeName)
81                     ?: bluePrintRepoService.getArtifactType(artifactTypeName)
82                     ?: throw BluePrintException("couldn't get ArtifactType($artifactTypeName) from repo.")
83             bluePrintContext.serviceTemplate.artifactTypes?.put(artifactTypeName, artifactType)
84             return artifactType
85         }
86
87         suspend fun copyFromFilePart(filePart: FilePart, targetFile: File): File {
88             // Delete the Directory
89             targetFile.deleteRecursively()
90             return filePart.transferTo(targetFile)
91                     .thenReturn(targetFile)
92                     .awaitSingle()
93         }
94
95         suspend fun extractCompressFilePart(filePart: FilePart, archiveDir: String, enhanceDir: String): File {
96             //Recreate the Base Directories
97             normalizedFile(archiveDir).reCreateDirs()
98             normalizedFile(enhanceDir).reCreateDirs()
99             val filePartFile = normalizedFile(archiveDir, "cba.zip")
100             // Copy the File Part to ZIP
101             return copyFromFilePart(filePart, filePartFile)
102         }
103
104         suspend fun decompressFilePart(filePart: FilePart, archiveDir: String, enhanceDir: String): File {
105             val filePartFile = extractCompressFilePart(filePart, archiveDir, enhanceDir)
106             val deCompressFileName = normalizedPathName(enhanceDir)
107             return filePartFile.deCompress(deCompressFileName)
108         }
109
110         suspend fun compressToFilePart(enhanceDir: String, archiveDir: String,
111                                        outputFileName:String="enhanced-cba.zip"): ResponseEntity<Resource> {
112             val compressedFile = normalizedFile(archiveDir, outputFileName)
113             BluePrintArchiveUtils.compress(Paths.get(enhanceDir).toFile(), compressedFile)
114             return prepareResourceEntity(compressedFile.name, compressedFile.readBytes())
115         }
116
117         suspend fun prepareResourceEntity(fileName: String, file: ByteArray): ResponseEntity<Resource> {
118             return ResponseEntity.ok()
119                     .contentType(MediaType.parseMediaType("text/plain"))
120                     .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"$fileName\"")
121                     .body(ByteArrayResource(file))
122         }
123
124         suspend fun cleanEnhancer(archiveLocation: String, enhancementLocation: String) = withContext(Dispatchers.Default) {
125             deleteDir(archiveLocation)
126             deleteDir(enhancementLocation)
127         }
128
129         /**
130          * This is a saveCBAFile method
131          * take a [FilePart], transfer it to disk using a Flux of FilePart and return a [Mono] representing the CBA file name
132          *
133          * @param (filePart, targetDirectory) - the request part containing the file to be saved and the default directory where to save
134          * @return a [Mono] String representing the result of the operation
135          * @throws (BluePrintException, IOException) BluePrintException, IOException
136          */
137         @Throws(BluePrintException::class, IOException::class)
138         fun saveCBAFile(filePart: FilePart, targetDirectory: Path): Mono<String> {
139
140             // Normalize file name
141             val fileName = StringUtils.cleanPath(filePart.filename())
142
143             // Check if the file's extension is "CBA"
144             if (StringUtils.getFilenameExtension(fileName) != "zip") {
145                 throw BluePrintException(ErrorCode.INVALID_FILE_EXTENSION.value, "Invalid file extension required ZIP")
146             }
147
148             // Change file name to match a pattern
149             val changedFileName = UUID.randomUUID().toString() + ".zip"
150             //String changedFileName = BluePrintFileUtils.Companion.getCBAGeneratedFileName(fileName, this.CBA_FILE_NAME_PATTERN);
151
152             // Copy file to the target location (Replacing existing file with the same name)
153             val targetLocation = targetDirectory.resolve(changedFileName)
154
155             // if a file with the same name already exists in a repository, delete and recreate it
156             val file = File(targetLocation.toString())
157             if (file.exists())
158                 file.delete()
159             file.createNewFile()
160
161             return filePart.transferTo(file).thenReturn(changedFileName)
162         }
163     }
164 }