f40da68f65578d41db629fd9fc55d66c3f04591b
[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.controllerblueprints.service.handler
20
21 import org.onap.ccsdk.cds.controllerblueprints.core.*
22 import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration
23 import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode
24 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService
25 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintEnhancerService
26 import org.onap.ccsdk.cds.controllerblueprints.service.domain.BlueprintModel
27 import org.onap.ccsdk.cds.controllerblueprints.service.domain.BlueprintModelSearch
28 import org.onap.ccsdk.cds.controllerblueprints.service.repository.ControllerBlueprintModelContentRepository
29 import org.onap.ccsdk.cds.controllerblueprints.service.repository.ControllerBlueprintModelRepository
30 import org.onap.ccsdk.cds.controllerblueprints.service.repository.ControllerBlueprintModelSearchRepository
31 import org.onap.ccsdk.cds.controllerblueprints.service.utils.BluePrintEnhancerUtils
32 import org.slf4j.LoggerFactory
33 import org.springframework.core.io.ByteArrayResource
34 import org.springframework.core.io.Resource
35 import org.springframework.http.HttpHeaders
36 import org.springframework.http.MediaType
37 import org.springframework.http.ResponseEntity
38 import org.springframework.http.codec.multipart.FilePart
39 import org.springframework.stereotype.Service
40 import org.springframework.transaction.annotation.Transactional
41 import java.io.File
42 import java.io.IOException
43 import java.util.*
44
45 /**
46  * BlueprintModelHandler Purpose: Handler service to handle the request from BlurPrintModelRest
47  *
48  * @author Brinda Santh
49  * @version 1.0
50  */
51
52 @Service
53 open class BluePrintModelHandler(private val controllerBlueprintsCatalogService: BluePrintCatalogService,
54                                  private val bluePrintLoadConfiguration: BluePrintLoadConfiguration,
55                                  private val blueprintModelSearchRepository: ControllerBlueprintModelSearchRepository,
56                                  private val blueprintModelRepository: ControllerBlueprintModelRepository,
57                                  private val blueprintModelContentRepository: ControllerBlueprintModelContentRepository,
58                                  private val bluePrintEnhancerService: BluePrintEnhancerService) {
59
60     private val log = LoggerFactory.getLogger(BluePrintModelHandler::class.java)!!
61
62     /**
63      * This is a getAllBlueprintModel method to retrieve all the BlueprintModel in Database
64      *
65      * @return List<BlueprintModelSearch> list of the controller blueprint archives
66     </BlueprintModelSearch> */
67     open fun allBlueprintModel(): List<BlueprintModelSearch> {
68         return blueprintModelSearchRepository.findAll()
69     }
70
71     /**
72      * This is a saveBlueprintModel method
73      *
74      * @param filePart filePart
75      * @return Mono<BlueprintModelSearch>
76      * @throws BluePrintException BluePrintException
77     </BlueprintModelSearch> */
78     @Throws(BluePrintException::class)
79     open suspend fun saveBlueprintModel(filePart: FilePart): BlueprintModelSearch {
80         val saveId = UUID.randomUUID().toString()
81         val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, saveId)
82         try {
83             //Recreate the Dir
84             normalizedFile(bluePrintLoadConfiguration.blueprintArchivePath, saveId).reCreateDirs()
85             val deCompressedFile = normalizedFile(blueprintArchive, "cba.zip")
86             // Copy the File Part to Local File
87             BluePrintEnhancerUtils.copyFromFilePart(filePart, deCompressedFile)
88             // Save the Copied file to Database
89             val blueprintId = controllerBlueprintsCatalogService.saveToDatabase(saveId, deCompressedFile, false)
90             // Check and Return the Saved File
91             val blueprintModelSearch = blueprintModelSearchRepository.findById(blueprintId).get()
92             log.info("Save($saveId) successful for blueprint(${blueprintModelSearch.artifactName}) " +
93                     "version(${blueprintModelSearch.artifactVersion})")
94             return blueprintModelSearch
95         } catch (e: IOException) {
96             throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
97                     "Error in Save CBA: ${e.message}", e)
98         } finally {
99             deleteDir(blueprintArchive)
100         }
101     }
102
103
104     /**
105      * This is a searchBlueprintModels method
106      *
107      * @param tags tags
108      * @return List<BlueprintModelSearch>
109     </BlueprintModelSearch> */
110     open fun searchBlueprintModels(tags: String): List<BlueprintModelSearch> {
111         return blueprintModelSearchRepository.findByTagsContainingIgnoreCase(tags)
112     }
113
114     /**
115      * This is a getBlueprintModelSearchByNameAndVersion method
116      *
117      * @param name name
118      * @param version version
119      * @return BlueprintModelSearch
120      * @throws BluePrintException BluePrintException
121      */
122     @Throws(BluePrintException::class)
123     open fun getBlueprintModelSearchByNameAndVersion(name: String, version: String): BlueprintModelSearch {
124         val blueprintModelSearch: BlueprintModelSearch
125         val dbBlueprintModel = blueprintModelSearchRepository
126                 .findByArtifactNameAndArtifactVersion(name, version)
127         if (dbBlueprintModel.isPresent) {
128             blueprintModelSearch = dbBlueprintModel.get()
129         } else {
130             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
131                     String.format(BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG, name, version))
132         }
133         return blueprintModelSearch
134     }
135
136     /**
137      * This is a downloadBlueprintModelFileByNameAndVersion method to download a Blueprint by Name and Version
138      *
139      * @param name name
140      * @param version version
141      * @return ResponseEntity<Resource>
142      * @throws BluePrintException BluePrintException
143     </Resource> */
144     @Throws(BluePrintException::class)
145     open fun downloadBlueprintModelFileByNameAndVersion(name: String,
146                                                         version: String): ResponseEntity<Resource> {
147         val blueprintModel: BlueprintModel
148         try {
149             blueprintModel = getBlueprintModelByNameAndVersion(name, version)
150         } catch (e: BluePrintException) {
151             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, String.format("Error while " + "downloading the CBA file: %s", e.message), e)
152         }
153
154         val fileName = blueprintModel.id + ".zip"
155         val file = blueprintModel.blueprintModelContent.content
156         return prepareResourceEntity(fileName, file)
157     }
158
159     /**
160      * This is a downloadBlueprintModelFile method to find the target file to download and return a file resource
161      *
162      * @return ResponseEntity<Resource>
163      * @throws BluePrintException BluePrintException
164     </Resource> */
165     @Throws(BluePrintException::class)
166     open fun downloadBlueprintModelFile(id: String): ResponseEntity<Resource> {
167         val blueprintModel: BlueprintModel
168         try {
169             blueprintModel = getBlueprintModel(id)
170         } catch (e: BluePrintException) {
171             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, String.format("Error while " + "downloading the CBA file: %s", e.message), e)
172         }
173
174         val fileName = blueprintModel.id + ".zip"
175         val file = blueprintModel.blueprintModelContent.content
176         return prepareResourceEntity(fileName, file)
177     }
178
179     /**
180      * @return ResponseEntity<Resource>
181     </Resource> */
182     private fun prepareResourceEntity(fileName: String, file: ByteArray): ResponseEntity<Resource> {
183         return ResponseEntity.ok()
184                 .contentType(MediaType.parseMediaType("text/plain"))
185                 .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"$fileName\"")
186                 .body(ByteArrayResource(file))
187     }
188
189     /**
190      * This is a getBlueprintModel method
191      *
192      * @param id id
193      * @return BlueprintModel
194      * @throws BluePrintException BluePrintException
195      */
196     @Throws(BluePrintException::class)
197     open fun getBlueprintModel(id: String): BlueprintModel {
198         val blueprintModel: BlueprintModel
199         val dbBlueprintModel = blueprintModelRepository.findById(id)
200         if (dbBlueprintModel.isPresent) {
201             blueprintModel = dbBlueprintModel.get()
202         } else {
203             val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
204             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
205         }
206         return blueprintModel
207     }
208
209     /**
210      * This is a getBlueprintModelByNameAndVersion method
211      *
212      * @param name name
213      * @param version version
214      * @return BlueprintModel
215      * @throws BluePrintException BluePrintException
216      */
217     @Throws(BluePrintException::class)
218     open fun getBlueprintModelByNameAndVersion(name: String, version: String): BlueprintModel {
219         val blueprintModel = blueprintModelRepository
220                 .findByArtifactNameAndArtifactVersion(name, version)
221         if (blueprintModel != null) {
222             return blueprintModel
223         } else {
224             val msg = String.format(BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG, name, version)
225             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
226         }
227     }
228
229     /**
230      * This is a getBlueprintModelSearch method
231      *
232      * @param id id
233      * @return BlueprintModelSearch
234      * @throws BluePrintException BluePrintException
235      */
236     @Throws(BluePrintException::class)
237     open fun getBlueprintModelSearch(id: String): BlueprintModelSearch {
238         val blueprintModelSearch: BlueprintModelSearch
239         val dbBlueprintModel = blueprintModelSearchRepository.findById(id)
240         if (dbBlueprintModel.isPresent) {
241             blueprintModelSearch = dbBlueprintModel.get()
242         } else {
243             val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
244             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
245         }
246
247         return blueprintModelSearch
248     }
249
250     /**
251      * This is a deleteBlueprintModel method
252      *
253      * @param id id
254      * @throws BluePrintException BluePrintException
255      */
256     @Transactional
257     @Throws(BluePrintException::class)
258     open fun deleteBlueprintModel(id: String) {
259         val dbBlueprintModel = blueprintModelRepository.findById(id)
260         if (dbBlueprintModel.isPresent) {
261             blueprintModelContentRepository.deleteByBlueprintModel(dbBlueprintModel.get())
262             blueprintModelRepository.delete(dbBlueprintModel.get())
263         } else {
264             val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
265             throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
266         }
267     }
268
269     /**
270      * This is a CBA enrichBlueprint method
271      * Save the Zip File in archive location and extract the cba content.
272      * Populate the Enhancement Location
273      * Enhance the CBA content
274      * Compress the Enhanced Content
275      * Return back the the compressed content back to the caller.
276      *
277      * @param filePart filePart
278      * @return ResponseEntity<Resource>
279      * @throws BluePrintException BluePrintException
280      */
281     @Throws(BluePrintException::class)
282     open suspend fun enrichBlueprint(filePart: FilePart): ResponseEntity<Resource> {
283         val enhanceId = UUID.randomUUID().toString()
284         val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, enhanceId)
285         val blueprintWorkingDir = normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, enhanceId)
286         try {
287             BluePrintEnhancerUtils.decompressFilePart(filePart, blueprintArchive, blueprintWorkingDir)
288
289             // Enhance the Blue Prints
290             bluePrintEnhancerService.enhance(blueprintWorkingDir)
291
292             return BluePrintEnhancerUtils.compressToFilePart(blueprintWorkingDir, blueprintArchive)
293
294         } catch (e: IOException) {
295             throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
296                     "Error in Enriching CBA: ${e.message}", e)
297         } finally {
298             BluePrintEnhancerUtils.cleanEnhancer(blueprintArchive, blueprintWorkingDir)
299         }
300     }
301
302     /**
303      * This is a publishBlueprintModel method to change the status published to YES
304      *
305      * @param filePart filePart
306      * @return BlueprintModelSearch
307      * @throws BluePrintException BluePrintException
308      */
309     @Throws(BluePrintException::class)
310     open suspend fun publishBlueprint(filePart: FilePart): BlueprintModelSearch {
311         val publishId = UUID.randomUUID().toString()
312         val blueprintArchive = bluePrintLoadConfiguration.blueprintArchivePath.plus(File.separator).plus(publishId)
313         val blueprintWorkingDir = bluePrintLoadConfiguration.blueprintWorkingPath.plus(File.separator).plus(publishId)
314         try {
315             val compressedFilePart = BluePrintEnhancerUtils
316                     .extractCompressFilePart(filePart, blueprintArchive, blueprintWorkingDir)
317
318             val blueprintId = controllerBlueprintsCatalogService.saveToDatabase(publishId, compressedFilePart, true)
319
320             return blueprintModelSearchRepository.findById(blueprintId).get()
321
322         } catch (e: Exception) {
323             throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
324                     "Error in Publishing CBA: ${e.message}", e)
325         } finally {
326             BluePrintEnhancerUtils.cleanEnhancer(blueprintArchive, blueprintWorkingDir)
327         }
328     }
329
330     companion object {
331
332         private const val BLUEPRINT_MODEL_ID_FAILURE_MSG = "failed to get blueprint model id(%s) from repo"
333         private const val BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG = "failed to get blueprint model by name(%s)" + " and version(%s) from repo"
334     }
335 }