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.http.HttpHeaders
39 import org.springframework.http.MediaType
40 import org.springframework.http.ResponseEntity
41 import org.springframework.http.codec.multipart.FilePart
42 import org.springframework.stereotype.Service
43 import org.springframework.transaction.annotation.Transactional
44 import java.io.IOException
46 import org.springframework.data.domain.Pageable
50 * BlueprintModelHandler Purpose: Handler service to handle the request from BlurPrintModelRest
52 * @author Brinda Santh
57 open class BluePrintModelHandler(private val blueprintsProcessorCatalogService: BluePrintCatalogService,
58 private val bluePrintLoadConfiguration: BluePrintLoadConfiguration,
59 private val blueprintModelSearchRepository: BlueprintModelSearchRepository,
60 private val blueprintModelRepository: BlueprintModelRepository,
61 private val blueprintModelContentRepository: BlueprintModelContentRepository,
62 private val bluePrintEnhancerService: BluePrintEnhancerService) {
64 private val log = logger(BluePrintModelHandler::class)
67 * This is a getAllBlueprintModel method to retrieve all the BlueprintModel in Database
69 * @return List<BlueprintModelSearch> list of the controller blueprint archives
70 </BlueprintModelSearch> */
71 open fun allBlueprintModel(): List<BlueprintModelSearch> {
72 return blueprintModelSearchRepository.findAll()
76 * This is a getAllBlueprintModel method to retrieve all the BlueprintModel in Database
78 * @return List<BlueprintModelSearch> list of the controller blueprint archives
79 </BlueprintModelSearch> */
80 open fun allBlueprintModel(pageRequest: Pageable): Page<BlueprintModelSearch> {
81 return blueprintModelSearchRepository.findAll(pageRequest)
85 * This is a saveBlueprintModel method
87 * @param filePart filePart
88 * @return Mono<BlueprintModelSearch>
89 * @throws BluePrintException BluePrintException
90 </BlueprintModelSearch> */
91 @Throws(BluePrintException::class)
92 open suspend fun saveBlueprintModel(filePart: FilePart): BlueprintModelSearch {
94 return upload(filePart, false)
95 } catch (e: IOException) {
96 throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
97 "Error in Save CBA: ${e.message}", e)
103 * This is a searchBlueprintModels method
106 * @return List<BlueprintModelSearch>
107 </BlueprintModelSearch> */
108 open fun searchBlueprintModels(tags: String): List<BlueprintModelSearch> {
109 return blueprintModelSearchRepository.findByTagsContainingIgnoreCase(tags)
113 * This is a getBlueprintModelSearchByNameAndVersion method
116 * @param version version
117 * @return BlueprintModelSearch
118 * @throws BluePrintException BluePrintException
120 @Throws(BluePrintException::class)
121 open fun getBlueprintModelSearchByNameAndVersion(name: String, version: String): BlueprintModelSearch {
122 return blueprintModelSearchRepository.findByArtifactNameAndArtifactVersion(name, version)
123 ?: throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
124 String.format(BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG, name, version))
129 * This is a downloadBlueprintModelFileByNameAndVersion method to download a Blueprint by Name and Version
132 * @param version version
133 * @return ResponseEntity<Resource>
134 * @throws BluePrintException BluePrintException
136 @Throws(BluePrintException::class)
137 open fun downloadBlueprintModelFileByNameAndVersion(name: String,
138 version: String): ResponseEntity<Resource> {
140 val archiveByteArray = download(name, version)
141 val fileName = "${name}_$version.zip"
142 return prepareResourceEntity(fileName, archiveByteArray)
143 } catch (e: BluePrintException) {
144 throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
145 String.format("Error while " + "downloading the CBA file: %s", e.message), e)
150 * This is a downloadBlueprintModelFile method to find the target file to download and return a file resource
152 * @return ResponseEntity<Resource>
153 * @throws BluePrintException BluePrintException
155 @Throws(BluePrintException::class)
156 open fun downloadBlueprintModelFile(id: String): ResponseEntity<Resource> {
157 val blueprintModel: BlueprintModel
159 blueprintModel = getBlueprintModel(id)
160 } catch (e: BluePrintException) {
161 throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, String.format("Error while " + "downloading the CBA file: %s", e.message), e)
164 val fileName = "${blueprintModel.artifactName}_${blueprintModel.artifactVersion}.zip"
165 val file = blueprintModel.blueprintModelContent?.content
166 ?: throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
167 String.format("Error while downloading the CBA file: couldn't get model content"))
168 return prepareResourceEntity(fileName, file)
172 * @return ResponseEntity<Resource>
174 private fun prepareResourceEntity(fileName: String, file: ByteArray): ResponseEntity<Resource> {
175 return ResponseEntity.ok()
176 .contentType(MediaType.parseMediaType("text/plain"))
177 .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"$fileName\"")
178 .body(ByteArrayResource(file))
182 * This is a getBlueprintModel method
185 * @return BlueprintModel
186 * @throws BluePrintException BluePrintException
188 @Throws(BluePrintException::class)
189 open fun getBlueprintModel(id: String): BlueprintModel {
190 val blueprintModel: BlueprintModel
191 val dbBlueprintModel = blueprintModelRepository.findById(id)
192 if (dbBlueprintModel.isPresent) {
193 blueprintModel = dbBlueprintModel.get()
195 val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
196 throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
198 return blueprintModel
202 * This is a getBlueprintModelByNameAndVersion method
205 * @param version version
206 * @return BlueprintModel
207 * @throws BluePrintException BluePrintException
209 @Throws(BluePrintException::class)
210 open fun getBlueprintModelByNameAndVersion(name: String, version: String): BlueprintModel {
211 val blueprintModel = blueprintModelRepository
212 .findByArtifactNameAndArtifactVersion(name, version)
213 if (blueprintModel != null) {
214 return blueprintModel
216 val msg = String.format(BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG, name, version)
217 throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
222 * This is a getBlueprintModelSearch method
225 * @return BlueprintModelSearch
226 * @throws BluePrintException BluePrintException
228 @Throws(BluePrintException::class)
229 open fun getBlueprintModelSearch(id: String): BlueprintModelSearch {
230 return blueprintModelSearchRepository.findById(id)
231 ?: throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
232 String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id))
236 * This is a searchBluePrintModelsByKeyWord method to retrieve specific BlueprintModel in Database
237 * where keyword equals updatedBy or tags or artifcat name or artifcat version or artifact type
238 * @author Shaaban Ebrahim
241 * @return List<BlueprintModelSearch> list of the controller blueprint
242 </BlueprintModelSearch> */
243 open fun searchBluePrintModelsByKeyWord(keyWord: String): List<BlueprintModelSearch> {
244 return blueprintModelSearchRepository.
245 findByUpdatedByOrTagsOrOrArtifactNameOrOrArtifactVersionOrArtifactType(
246 keyWord,keyWord,keyWord,keyWord,keyWord)
250 * This is a deleteBlueprintModel method
253 * @throws BluePrintException BluePrintException
256 @Throws(BluePrintException::class)
257 open fun deleteBlueprintModel(id: String) {
258 val dbBlueprintModel = blueprintModelRepository.findById(id)
259 if (dbBlueprintModel != null && dbBlueprintModel.isPresent) {
260 blueprintModelContentRepository.deleteByBlueprintModel(dbBlueprintModel.get())
261 blueprintModelRepository.delete(dbBlueprintModel.get())
263 val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)
264 throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg)
268 open suspend fun deleteBlueprintModel(name: String, version: String) {
269 blueprintsProcessorCatalogService.deleteFromDatabase(name, version)
273 * This is a CBA enrichBlueprint method
274 * Save the Zip File in archive location and extract the cba content.
275 * Populate the Enhancement Location
276 * Enhance the CBA content
277 * Compress the Enhanced Content
278 * Return back the the compressed content back to the caller.
280 * @param filePart filePart
281 * @return ResponseEntity<Resource>
282 * @throws BluePrintException BluePrintException
284 @Throws(BluePrintException::class)
285 open suspend fun enrichBlueprint(filePart: FilePart): ResponseEntity<Resource> {
287 val enhancedByteArray = enrichBlueprintFileSource(filePart)
288 return BluePrintEnhancerUtils.prepareResourceEntity("enhanced-cba.zip", enhancedByteArray)
289 } catch (e: IOException) {
290 throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
291 "Error in Enriching CBA: ${e.message}", e)
296 * This is a publishBlueprintModel method to change the status published to YES
298 * @param filePart filePart
299 * @return BlueprintModelSearch
300 * @throws BluePrintException BluePrintException
302 @Throws(BluePrintException::class)
303 open suspend fun publishBlueprint(filePart: FilePart): BlueprintModelSearch {
305 return upload(filePart, true)
306 } catch (e: Exception) {
307 throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
308 "Error in Publishing CBA: ${e.message}", e)
312 /** Common CBA Save and Publish function for RestController and GRPC Handler, the [fileSource] may be
313 * byteArray or File Part type.*/
314 open suspend fun upload(fileSource: Any, validate: Boolean): BlueprintModelSearch {
315 val saveId = UUID.randomUUID().toString()
316 val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, saveId)
317 val blueprintWorking = normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, saveId)
319 val compressedFile = normalizedFile(blueprintArchive, "cba.zip")
321 is FilePart -> BluePrintEnhancerUtils.filePartAsFile(fileSource, compressedFile)
322 is ByteArray -> BluePrintEnhancerUtils.byteArrayAsFile(fileSource, compressedFile)
324 // Save the Copied file to Database
325 val blueprintId = blueprintsProcessorCatalogService.saveToDatabase(saveId, compressedFile, validate)
327 return blueprintModelSearchRepository.findById(blueprintId)
328 ?: throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
329 String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, blueprintId))
331 } catch (e: IOException) {
332 throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
333 "Error in Upload CBA: ${e.message}", e)
335 // Clean blueprint script cache
336 val cacheKey = BluePrintFileUtils
337 .compileCacheKey(normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, saveId))
338 BluePrintCompileCache.cleanClassLoader(cacheKey)
339 deleteNBDir(blueprintArchive)
340 deleteNBDir(blueprintWorking)
344 /** Common CBA download function for RestController and GRPC Handler, the [fileSource] may be
345 * byteArray or File Part type.*/
346 open fun download(name: String, version: String): ByteArray {
348 val blueprintModel = getBlueprintModelByNameAndVersion(name, version)
349 return blueprintModel.blueprintModelContent?.content
350 ?: throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
351 String.format("Error while downloading the CBA file: couldn't get model content"))
352 } catch (e: BluePrintException) {
353 throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
354 String.format("Error while " + "downloading the CBA file: %s", e.message), e)
358 /** Common CBA Enrich function for RestController and GRPC Handler, the [fileSource] may be
359 * byteArray or File Part type.*/
360 open suspend fun enrichBlueprintFileSource(fileSource: Any): ByteArray {
361 val enhanceId = UUID.randomUUID().toString()
362 val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, enhanceId)
363 val blueprintWorkingDir = normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, enhanceId)
366 is FilePart -> BluePrintEnhancerUtils
367 .copyFilePartToEnhanceDir(fileSource, blueprintArchive, blueprintWorkingDir)
368 is ByteArray -> BluePrintEnhancerUtils
369 .copyByteArrayToEnhanceDir(fileSource, blueprintArchive, blueprintWorkingDir)
370 } // Enhance the Blue Prints
371 bluePrintEnhancerService.enhance(blueprintWorkingDir)
373 return BluePrintEnhancerUtils.compressEnhanceDirAndReturnByteArray(blueprintWorkingDir, blueprintArchive)
375 } catch (e: IOException) {
376 throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
377 "Error in Enriching CBA: ${e.message}", e)
379 BluePrintEnhancerUtils.cleanEnhancer(blueprintArchive, blueprintWorkingDir)
385 private const val BLUEPRINT_MODEL_ID_FAILURE_MSG = "failed to get blueprint model id(%s) from repo"
386 private const val BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG = "failed to get blueprint model by name(%s)" + " and version(%s) from repo"