02140ebf7011f0265d6c726b996d5e4916b3e379
[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.apps.controllerblueprints.service.utils
20
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
40 import java.io.File
41 import java.io.IOException
42 import java.nio.file.Path
43 import java.nio.file.Paths
44 import java.util.*
45
46
47 class BluePrintEnhancerUtils {
48     companion object {
49
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)
56             return dataType
57         }
58
59         fun populateRelationshipType(bluePrintContext: BluePrintContext, bluePrintRepoService: BluePrintRepoService,
60                                      relationshipName: String): RelationshipType {
61
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
67         }
68
69
70         fun populateNodeType(bluePrintContext: BluePrintContext, bluePrintRepoService: BluePrintRepoService,
71                              nodeTypeName: String): NodeType {
72
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)
77             return nodeType
78         }
79
80         fun populateArtifactType(bluePrintContext: BluePrintContext, bluePrintRepoService: BluePrintRepoService,
81                                  artifactTypeName: String): ArtifactType {
82
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)
87             return artifactType
88         }
89
90         suspend fun copyFromFilePart(filePart: FilePart, targetFile: File): File {
91             // Delete the Directory
92             targetFile.deleteRecursively()
93             return filePart.transferTo(targetFile)
94                     .thenReturn(targetFile)
95                     .awaitSingle()
96         }
97
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()
102
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)
108         }
109
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())
114         }
115
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))
121         }
122
123         suspend fun cleanEnhancer(archiveLocation: String, enhancementLocation: String) = withContext(Dispatchers.Default) {
124             val enrichDir = File(enhancementLocation)
125             FileUtils.forceDeleteOnExit(enrichDir)
126
127             val archiveDir = File(archiveLocation)
128             FileUtils.forceDeleteOnExit(archiveDir)
129         }
130
131         /**
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
134          *
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
138          */
139         @Throws(BluePrintException::class, IOException::class)
140         fun saveCBAFile(filePart: FilePart, targetDirectory: Path): Mono<String> {
141
142             // Normalize file name
143             val fileName = StringUtils.cleanPath(filePart.filename())
144
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")
148             }
149
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);
153
154             // Copy file to the target location (Replacing existing file with the same name)
155             val targetLocation = targetDirectory.resolve(changedFileName)
156
157             // if a file with the same name already exists in a repository, delete and recreate it
158             val file = File(targetLocation.toString())
159             if (file.exists())
160                 file.delete()
161             file.createNewFile()
162
163             return filePart.transferTo(file).thenReturn(changedFileName)
164         }
165     }
166 }