2 * Copyright © 2017-2018 AT&T Intellectual Property.
3 * Modifications Copyright © 2019 Bell Canada.
4 * Modifications Copyright © 2019 IBM.
5 * Modifications Copyright © 2019 Orange.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
20 package org.onap.ccsdk.cds.blueprintsprocessor.designer.api.handler
22 import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.domain.BlueprintModel
23 import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.domain.BlueprintModelSearch
24 import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.repository.BlueprintModelContentRepository
25 import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.repository.BlueprintModelRepository
26 import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.repository.BlueprintModelSearchRepository
27 import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.utils.BluePrintEnhancerUtils
28 import org.onap.ccsdk.cds.controllerblueprints.core.*
29 import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration
30 import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode
31 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService
32 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintEnhancerService
33 import org.onap.ccsdk.cds.controllerblueprints.core.scripts.BluePrintCompileCache
34 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintFileUtils
35 import org.springframework.core.io.ByteArrayResource
36 import org.springframework.core.io.Resource
37 import org.springframework.data.domain.Page
38 import org.springframework.data.domain.PageRequest
39 import org.springframework.http.HttpHeaders
40 import org.springframework.http.MediaType
41 import org.springframework.http.ResponseEntity
42 import org.springframework.http.codec.multipart.FilePart
43 import org.springframework.stereotype.Service
44 import org.springframework.transaction.annotation.Transactional
45 import java.io.IOException
47 import org.springframework.data.domain.Pageable
51 * BlueprintModelHandler Purpose: Handler service to handle the request from BlurPrintModelRest
53 * @author Brinda Santh
58 open class BluePrintModelHandler(private val blueprintsProcessorCatalogService: BluePrintCatalogService,
59 private val bluePrintLoadConfiguration: BluePrintLoadConfiguration,
60 private val blueprintModelSearchRepository: BlueprintModelSearchRepository,
61 private val blueprintModelRepository: BlueprintModelRepository,
62 private val blueprintModelContentRepository: BlueprintModelContentRepository,
63 private val bluePrintEnhancerService: BluePrintEnhancerService) {
65 private val log = logger(BluePrintModelHandler::class)
68 * This is a getAllBlueprintModel method to retrieve all the BlueprintModel in Database
70 * @return List<BlueprintModelSearch> list of the controller blueprint archives
71 </BlueprintModelSearch> */
72 open fun allBlueprintModel(): List<BlueprintModelSearch> {
73 return blueprintModelSearchRepository.findAll()
77 * This is a getAllBlueprintModel method to retrieve all the BlueprintModel in Database
79 * @return List<BlueprintModelSearch> list of the controller blueprint archives
80 </BlueprintModelSearch> */
81 open fun allBlueprintModel(pageRequest: Pageable): Page<BlueprintModelSearch> {
82 return blueprintModelSearchRepository.findAll(pageRequest)
86 * This is a saveBlueprintModel method
88 * @param filePart filePart
89 * @return Mono<BlueprintModelSearch>
90 * @throws BluePrintException BluePrintException
91 </BlueprintModelSearch> */
92 @Throws(BluePrintException::class)
93 open suspend fun saveBlueprintModel(filePart: FilePart): BlueprintModelSearch {
95 return upload(filePart, false)
96 } catch (e: IOException) {
97 throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
98 "Error in Save CBA: ${e.message}", e)
104 * This is a searchBlueprintModels method
107 * @return List<BlueprintModelSearch>
108 </BlueprintModelSearch> */
109 open fun searchBlueprintModels(tags: String): List<BlueprintModelSearch> {
110 return blueprintModelSearchRepository.findByTagsContainingIgnoreCase(tags)
114 * This is a getBlueprintModelSearchByNameAndVersion method
117 * @param version version
118 * @return BlueprintModelSearch
119 * @throws BluePrintException BluePrintException
121 @Throws(BluePrintException::class)
122 open fun getBlueprintModelSearchByNameAndVersion(name: String, version: String): BlueprintModelSearch {
123 return blueprintModelSearchRepository.findByArtifactNameAndArtifactVersion(name, version)
124 ?: throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
125 String.format(BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG, name, version))
130 * This is a downloadBlueprintModelFileByNameAndVersion method to download a Blueprint by Name and Version
133 * @param version version
134 * @return ResponseEntity<Resource>
135 * @throws BluePrintException BluePrintException
137 @Throws(BluePrintException::class)
138 open fun downloadBlueprintModelFileByNameAndVersion(name: String,
139 version: String): ResponseEntity<Resource> {
141 val archiveByteArray = download(name, version)
142 val fileName = "${name}_$version.zip"
143 return prepareResourceEntity(fileName, archiveByteArray)
144 } catch (e: BluePrintException) {
145 throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
146 String.format("Error while " + "downloading the CBA file: %s", e.message), e)
151 * This is a downloadBlueprintModelFile method to find the target file to download and return a file resource
153 * @return ResponseEntity<Resource>
154 * @throws BluePrintException BluePrintException
156 @Throws(BluePrintException::class)
157 open fun downloadBlueprintModelFile(id: String): ResponseEntity<Resource> {
158 val blueprintModel: BlueprintModel
160 blueprintModel = getBlueprintModel(id)
161 } catch (e: BluePrintException) {
162 throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, String.format("Error while " + "downloading the CBA file: %s", e.message), e)
165 val fileName = "${blueprintModel.artifactName}_${blueprintModel.artifactVersion}.zip"
166 val file = blueprintModel.blueprintModelContent?.content
167 ?: throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
168 String.format("Error while downloading the CBA file: couldn't get model content"))
169 return prepareResourceEntity(fileName, file)
173 * @return ResponseEntity<Resource>
175 private fun prepareResourceEntity(fileName: String, file: ByteArray): ResponseEntity<Resource> {
176 return ResponseEntity.ok()
177 .contentType(MediaType.parseMediaType("text/plain"))
178 .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"$fileName\"")
179 .body(ByteArrayResource(file))
183 * This is a getBlueprintModel method
186 * @return BlueprintModel
187 * @throws BluePrintException BluePrintException
189 @Throws(BluePrintException::class)
190 open fun getBlueprintModel(id: String): BlueprintModel {
191 val blueprintModel: BlueprintModel
192 val dbBlueprintModel = blueprintModelRepository.findById(id)
193 if (dbBlueprintModel.isPresent) {
194 blueprintModel = dbBlueprintModel.get()
196 val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
197 throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
199 return blueprintModel
203 * This is a getBlueprintModelByNameAndVersion method
206 * @param version version
207 * @return BlueprintModel
208 * @throws BluePrintException BluePrintException
210 @Throws(BluePrintException::class)
211 open fun getBlueprintModelByNameAndVersion(name: String, version: String): BlueprintModel {
212 val blueprintModel = blueprintModelRepository
213 .findByArtifactNameAndArtifactVersion(name, version)
214 if (blueprintModel != null) {
215 return blueprintModel
217 val msg = String.format(BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG, name, version)
218 throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
223 * This is a getBlueprintModelSearch method
226 * @return BlueprintModelSearch
227 * @throws BluePrintException BluePrintException
229 @Throws(BluePrintException::class)
230 open fun getBlueprintModelSearch(id: String): BlueprintModelSearch {
231 return blueprintModelSearchRepository.findById(id)
232 ?: throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
233 String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id))
237 * This is a searchBluePrintModelsByKeyWord method to retrieve specific BlueprintModel in Database
238 * where keyword equals updatedBy or tags or artifcat name or artifcat version or artifact type
239 * @author Shaaban Ebrahim
242 * @return List<BlueprintModelSearch> list of the controller blueprint
243 </BlueprintModelSearch> */
244 open fun searchBluePrintModelsByKeyWord(keyWord: String): List<BlueprintModelSearch> {
245 return blueprintModelSearchRepository.
246 findByUpdatedByOrTagsOrOrArtifactNameOrOrArtifactVersionOrArtifactType(
247 keyWord,keyWord,keyWord,keyWord,keyWord)
253 * This is a searchBluePrintModelsByKeyWordPagebale method to retrieve specific BlueprintModel in Database
254 * where keyword equals updatedBy or tags or artifcat name or artifcat version or artifact type and pageable
255 * @author Shaaban Ebrahim
258 * @return List<BlueprintModelSearch> list of the controller blueprint
259 </BlueprintModelSearch> */
260 open fun searchBluePrintModelsByKeyWordPaged(keyWord: String, pageRequest: PageRequest): Page<BlueprintModelSearch>
262 return blueprintModelSearchRepository.
263 findByUpdatedByOrTagsOrOrArtifactNameOrOrArtifactVersionOrArtifactType(keyWord,keyWord,keyWord,keyWord,keyWord,pageRequest)
266 * This is a deleteBlueprintModel method
269 * @throws BluePrintException BluePrintException
272 @Throws(BluePrintException::class)
273 open fun deleteBlueprintModel(id: String) {
274 val dbBlueprintModel = blueprintModelRepository.findById(id)
275 if (dbBlueprintModel != null && dbBlueprintModel.isPresent) {
276 blueprintModelContentRepository.deleteByBlueprintModel(dbBlueprintModel.get())
277 blueprintModelRepository.delete(dbBlueprintModel.get())
279 val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
280 throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
284 open suspend fun deleteBlueprintModel(name: String, version: String) {
285 blueprintsProcessorCatalogService.deleteFromDatabase(name, version)
289 * This is a CBA enrichBlueprint method
290 * Save the Zip File in archive location and extract the cba content.
291 * Populate the Enhancement Location
292 * Enhance the CBA content
293 * Compress the Enhanced Content
294 * Return back the the compressed content back to the caller.
296 * @param filePart filePart
297 * @return ResponseEntity<Resource>
298 * @throws BluePrintException BluePrintException
300 @Throws(BluePrintException::class)
301 open suspend fun enrichBlueprint(filePart: FilePart): ResponseEntity<Resource> {
303 val enhancedByteArray = enrichBlueprintFileSource(filePart)
304 return BluePrintEnhancerUtils.prepareResourceEntity("enhanced-cba.zip", enhancedByteArray)
305 } catch (e: IOException) {
306 throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
307 "Error in Enriching CBA: ${e.message}", e)
312 * This is a publishBlueprintModel method to change the status published to YES
314 * @param filePart filePart
315 * @return BlueprintModelSearch
316 * @throws BluePrintException BluePrintException
318 @Throws(BluePrintException::class)
319 open suspend fun publishBlueprint(filePart: FilePart): BlueprintModelSearch {
321 return upload(filePart, true)
322 } catch (e: Exception) {
323 throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
324 "Error in Publishing CBA: ${e.message}", e)
328 /** Common CBA Save and Publish function for RestController and GRPC Handler, the [fileSource] may be
329 * byteArray or File Part type.*/
330 open suspend fun upload(fileSource: Any, validate: Boolean): BlueprintModelSearch {
331 val saveId = UUID.randomUUID().toString()
332 val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, saveId)
333 val blueprintWorking = normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, saveId)
335 val compressedFile = normalizedFile(blueprintArchive, "cba.zip")
337 is FilePart -> BluePrintEnhancerUtils.filePartAsFile(fileSource, compressedFile)
338 is ByteArray -> BluePrintEnhancerUtils.byteArrayAsFile(fileSource, compressedFile)
340 // Save the Copied file to Database
341 val blueprintId = blueprintsProcessorCatalogService.saveToDatabase(saveId, compressedFile, validate)
343 return blueprintModelSearchRepository.findById(blueprintId)
344 ?: throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
345 String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, blueprintId))
347 } catch (e: IOException) {
348 throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
349 "Error in Upload CBA: ${e.message}", e)
351 // Clean blueprint script cache
352 val cacheKey = BluePrintFileUtils
353 .compileCacheKey(normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, saveId))
354 BluePrintCompileCache.cleanClassLoader(cacheKey)
355 deleteNBDir(blueprintArchive)
356 deleteNBDir(blueprintWorking)
360 /** Common CBA download function for RestController and GRPC Handler, the [fileSource] may be
361 * byteArray or File Part type.*/
362 open fun download(name: String, version: String): ByteArray {
364 val blueprintModel = getBlueprintModelByNameAndVersion(name, version)
365 return blueprintModel.blueprintModelContent?.content
366 ?: throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
367 String.format("Error while downloading the CBA file: couldn't get model content"))
368 } catch (e: BluePrintException) {
369 throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
370 String.format("Error while " + "downloading the CBA file: %s", e.message), e)
374 /** Common CBA Enrich function for RestController and GRPC Handler, the [fileSource] may be
375 * byteArray or File Part type.*/
376 open suspend fun enrichBlueprintFileSource(fileSource: Any): ByteArray {
377 val enhanceId = UUID.randomUUID().toString()
378 val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, enhanceId)
379 val blueprintWorkingDir = normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, enhanceId)
382 is FilePart -> BluePrintEnhancerUtils
383 .copyFilePartToEnhanceDir(fileSource, blueprintArchive, blueprintWorkingDir)
384 is ByteArray -> BluePrintEnhancerUtils
385 .copyByteArrayToEnhanceDir(fileSource, blueprintArchive, blueprintWorkingDir)
386 } // Enhance the Blue Prints
387 bluePrintEnhancerService.enhance(blueprintWorkingDir)
389 return BluePrintEnhancerUtils.compressEnhanceDirAndReturnByteArray(blueprintWorkingDir, blueprintArchive)
391 } catch (e: IOException) {
392 throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
393 "Error in Enriching CBA: ${e.message}", e)
395 BluePrintEnhancerUtils.cleanEnhancer(blueprintArchive, blueprintWorkingDir)
401 private const val BLUEPRINT_MODEL_ID_FAILURE_MSG = "failed to get blueprint model id(%s) from repo"
402 private const val BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG = "failed to get blueprint model by name(%s)" + " and version(%s) from repo"